Skip to content

一、用户管理

用户抽象类实现,主要用于定义用户(Target)的行为和属性。:

typescript
    export abstract class Target extends Team implements ITarget

用户初始化

  • 方法Target类的构造函数

  • 功能:初始化用户的基本属性(如会话、资源、目录等),并设置缓存机制。通过setTimeout延迟加载用户数据,确保初始化过程的异步性。

    typescript
    constructor(
      _keys: string[],
      _metadata: schema.XTarget,
      _relations: string[],
      _space?: IBelong,
      _user?: IPerson,
      _memberTypes: TargetType[] = [TargetType.Person],
    ) {
      super(_keys, _metadata, _relations, _memberTypes);
      // 初始化用户的基本属性
      this.space = _space || (this as unknown as IBelong);
      this.user = _user || (this as unknown as IPerson);
      this.cacheObj = new XObject(_metadata, 'target-cache', [], [this.key]);
      this.resource = new DataResource(_metadata, _relations, [this.key]);
      this.directory = new Directory(
        {
          ..._metadata,
          shareId: _metadata.id,
          id: _metadata.id + '_',
          typeName: '目录',
        } as unknown as schema.XDirectory,
        this,
      );
      this.memberDirectory = new MemberDirectory(this);
      this.session = new Session(this.id, this, _metadata);
      this.recorder = new Recorder(this);
      this.path = [..._relations];
      // 延迟加载用户数据
      setTimeout(
        async () => {
          await this.loadUserData(_keys, _metadata);
        },
        this.id === this.userId ? 100 : 0,
      );
    }

用户数据缓存

  • 方法loadUserDatacacheUserData

  • 功能

    • loadUserData:加载用户数据并订阅身份变更事件。
    • cacheUserData:缓存用户数据,并在数据变化时通知其他用户。
    typescript
    async loadUserData(keys: string[], _metadata: schema.XTarget): Promise<void> {
      kernel.subscribe(
        `${_metadata.belongId}-${_metadata.id}-identity`,
        keys,
        (data: any) => this._receiveIdentity(data),
      );
      const data = await this.user.cacheObj.get<schema.XCache>(this.cachePath);
      if (data && data.fullId === this.cache.fullId) {
        this.cache = data;
      }
      this.user.cacheObj.subscribe(this.cachePath, (data: schema.XCache) => {
        if (data && data.fullId === this.cache.fullId) {
          this.cache = data;
          this.user.cacheObj.setValue(this.cachePath, data);
          this.directory.changCallback();
        }
      });
    }
    
    async cacheUserData(notify: boolean = true): Promise<boolean> {
      const success = await this.user.cacheObj.set(this.cachePath, this.cache);
      if (success && notify) {
        await this.user.cacheObj.notity(this.cachePath, this.cache, true, true);
      }
      return success;
    }

身份管理

  • 方法loadIdentityscreateIdentitysendIdentityChangeMsg

  • 功能

    • loadIdentitys:从后端查询用户的身份,并缓存到identitys列表中。
    • createIdentity:创建新的身份,并通知相关用户身份变更。
    • sendIdentityChangeMsg:发送身份变更通知,确保所有相关用户及时收到更新。
    typescript
    async loadIdentitys(reload?: boolean | undefined): Promise<IIdentity[]> {
      if (!this._identityLoaded || reload) {
        const res = await kernel.queryTargetIdentitys({
          id: this.id,
          page: PageAll,
        });
        if (res.success) {
          this._identityLoaded = true;
          this.identitys = (res.data.result || []).map((item) => {
            return new Identity(item, this);
          });
        }
      }
      return this.identitys;
    }
    
    async createIdentity(data: model.IdentityModel): Promise<IIdentity | undefined> {
      data.shareId = this.id;
      const res = await kernel.createIdentity(data);
      if (res.success && res.data?.id) {
        const identity = new Identity(res.data, this);
        this.identitys.push(identity);
        identity._sendIdentityChangeMsg(OperateType.Create, this.metadata);
        return identity;
      }
    }
    
    async sendIdentityChangeMsg(data: any): Promise<boolean> {
      const res = await kernel.dataNotify({
        data: data,
        flag: 'identity',
        onlineOnly: true,
        belongId: this.metadata.belongId,
        relations: this.relations,
        onlyTarget: false,
        ignoreSelf: true,
        targetId: this.metadata.id,
        targetType: 'target',
      });
      return res.success;
    }

会话管理

  • 方法notifySession

  • 功能:通知会话中的成员加入或退出,确保会话状态的一致性。

    typescript
    async notifySession(pull: boolean, members: schema.XTarget[]): Promise<void> {
      if (this.id != this.userId && this.typeName !== '存储资源') {
        for (const member of members) {
          if (member.typeName === TargetType.Person) {
            if (pull) {
              await this.session.sendMessage(
                MessageType.Notify,
                `${this.user.name} 邀请 ${member.name} 加入群聊`,
                [],
              );
            } else {
              await this.session.sendMessage(
                MessageType.Notify,
                `${this.user.name} 将 ${member.name} 移出群聊`,
                [],
              );
            }
          }
        }
      }
    }

转换为组织分类

  • 方法toSpecies

  • 功能:将用户转换为组织分类,递归生成分类项,确保用户结构的完整性和一致性。

    typescript
    async toSpecies(dest: IDirectory): Promise<schema.XSpecies | undefined> {
      const ret = await dest.standard.createSpecies({
        generateTargetId: this.metadata.id,
        name: this.metadata.name,
        code: this.metadata.code,
        remark: this.metadata.remark,
        icon: this.metadata.icon,
        tags: '组织分类',
        typeName: '分类',
        belongId: dest.belongId,
        shareId: dest.target.id,
      } as schema.XSpecies);
      if (ret) {
        const genSpeciesItem = async (species: ISpecies, team: ITarget) => {
          const toSpeciesItem = (target: schema.XTarget, parentId?: string) => {
            return {
              code: target.code,
              parentId: parentId,
              name: target.name,
              info: target.id,
              remark: target.name,
              icon: target.icon,
              belongId: dest.target.space.id,
              shareId: dest.target.id,
              typeName: '分类项',
            } as unknown as schema.XSpeciesItem;
          };
          const itemRet = await species.createItem(toSpeciesItem(team.metadata));
          if (itemRet) {
            for (const member of team.members) {
              if (member.typeName !== TargetType.Person) {
                await species.createItem(toSpeciesItem(member, itemRet.id));
              }
            }
            for (const child of team.subTarget) {
              await genSpeciesItem(species, child);
            }
          }
        };
        genSpeciesItem(new Species(ret, dest), this);
      }
      return;
    }

事件通知

  • 方法_receiveIdentity

  • 功能:处理身份变更事件,更新本地缓存并通知其他用户。

    typescript
    private async _receiveIdentity(data: model.IdentityOperateModel) {
      let message = '';
      switch (data.operate) {
        case OperateType.Create:
          message = `${data.operater.name}新增身份【${data.identity.name}】.`;
          if (this.identitys.every((q) => q.id !== data.identity.id)) {
            this.identitys.push(new Identity(data.identity, this));
          }
          break;
        case OperateType.Delete:
          message = `${data.operater.name}将身份【${data.identity.name}】删除.`;
          await this.identitys.find((a) => a.id == data.identity.id)?.delete(true);
          break;
        case OperateType.Update:
          message = `${data.operater.name}将身份【${data.identity.name}】信息更新.`;
          this.updateMetadata(data.identity);
          break;
        case OperateType.Remove:
          if (data.subTarget) {
            message = `${data.operater.name}移除赋予【${data.subTarget!.name}】的身份【${
              data.identity.name
            }】.`;
            await this.identitys
              .find((a) => a.id == data.identity.id)
              ?.removeMembers([data.subTarget], true);
          }
          break;
        case OperateType.Add:
          if (data.subTarget) {
            message = `${data.operater.name}赋予{${data.subTarget!.name}身份【${
              data.identity.name
            }】.`;
            await this.identitys
              .find((a) => a.id == data.identity.id)
              ?.pullMembers([data.subTarget], true);
          }
          break;
      }
      if (message.length > 0) {
        if (data.operater?.id != this.user.id) {
          logger.info(message);
        }
        this.changCallback();
        this.directory.changCallback();
      }
    }

二、角色管理接口与实现类

IIdentity 接口

typescript
export interface IIdentity extends IEntity<schema.XIdentity> {
  /** 设置身份(角色)的用户 */
  current: ITarget;
  /** 赋予身份(角色)的成员用户 */
  members: schema.XTarget[];
  /** 加载成员用户实体 */
  loadMembers(reload?: boolean): Promise<schema.XTarget[]>;
  /** 身份(角色)拉入新成员 */
  pullMembers(members: schema.XTarget[], notity?: boolean): Promise<boolean>;
  /** 身份(角色)移除成员 */
  removeMembers(members: schema.XTarget[], notity?: boolean): Promise<boolean>;
  /** 更新身份(角色)信息 */
  update(data: model.IdentityModel): Promise<boolean>;
  /** 删除身份(角色) */
  delete(notity?: boolean): Promise<boolean>;
}
  • 属性:

    • current: 当前角色所属的目标实体。
    • members: 角色的成员列表。
  • 方法:

    • loadMembers: 加载角色的成员列表。
    • pullMembers: 将新成员添加到角色中。
    • removeMembers: 从角色中移除成员。
    • update: 更新角色的信息。
    • delete: 删除角色。

Identity 类

Identity 类实现了角色管理的核心功能,包括成员的添加、移除、角色信息的更新和删除等操作。通过与系统内核的交互,确保角色管理操作的正确性和一致性。同时,通过操作通知机制,与其他系统组件保持同步。

typescript
export class Identity extends Entity<schema.XIdentity> implements IIdentity {
  constructor(_metadata: schema.XIdentity, current: ITarget) {
    super(
      {
        ..._metadata,
        typeName: '角色',
      },
      [],
    );
    this.current = current;
  }
  • 构造函数: 接收角色的元数据和当前目标实体,初始化角色对象。

方法实现

重命名角色

typescript
async rename(name: string): Promise<boolean> {
  return await this.update({ ...this.metadata, name: name });
}
  • 调用 update 方法更新角色名称。

复制和移动(未实现)

typescript
copy(_destination: IDirectory): Promise<boolean> {
  throw new Error('Method not implemented.');
}
move(_destination: IDirectory): Promise<boolean> {
  throw new Error('Method not implemented.');
}
  • 当前未实现复制和移动功能。

加载成员

typescript
private _memberLoaded: boolean = false;
async loadMembers(reload?: boolean | undefined): Promise<schema.XTarget[]> {
  if (!this._memberLoaded || reload) {
    const res = await kernel.queryIdentityTargets({
      id: this.id,
      page: PageAll,
    });
    if (res.success) {
      this._memberLoaded = true;
      this.members = res.data.result || [];
    }
  }
  return this.members;
}
  • 从后端加载角色的成员列表,支持重新加载。

添加成员

typescript
async pullMembers(
  members: schema.XTarget[],
  notity: boolean = false,
): Promise<boolean> {
  members = members.filter((i) => this.members.every((m) => m.id !== i.id));
  if (members.length > 0) {
    if (!notity) {
      const res = await kernel.giveIdentity({
        id: this.id,
        subIds: members.map((i) => i.id),
      });
      if (!res.success) return false;
      members.forEach((a) => this._sendIdentityChangeMsg(OperateType.Add, a));
    }
    this.members.push(...members);
    if (members.find((a) => a.id === this.userId)) {
      this.current.user.giveIdentity([this.metadata]);
    }
  }
  return true;
}
  • 将新成员添加到角色中,并通知系统。

移除成员

typescript
async removeMembers(
  members: schema.XTarget[],
  notity: boolean = false,
): Promise<boolean> {
  members = members.filter((i) => this.members.some((m) => m.id === i.id));
  if (members.length > 0) {
    if (!notity) {
      const res = await kernel.removeIdentity({
        id: this.id,
        subIds: members.map((i) => i.id),
      });
      if (!res.success) return false;
      members.forEach((a) => this._sendIdentityChangeMsg(OperateType.Remove, a));
    }
    if (members.some((a) => a.id === this.userId)) {
      this.current.user.removeGivedIdentity([this.id]);
    }
    this.members = this.members.filter((i) => members.every((s) => s.id !== i.id));
  }
  return true;
}
  • 从角色中移除成员,并通知系统。

更新角色信息

typescript
async update(data: model.IdentityModel): Promise<boolean> {
  data.id = this.id;
  data.shareId = this.metadata.shareId;
  data.name = data.name || this.name;
  data.code = data.code || this.code;
  data.authId = data.authId || this.metadata.authId;
  data.remark = data.remark || this.remark;
  const res = await kernel.updateIdentity(data);
  if (res.success && res.data?.id) {
    res.data.typeName = '角色';
    this.setMetadata(res.data);
    this._sendIdentityChangeMsg(OperateType.Update);
  }
  return res.success;
}
  • 更新角色的元数据信息。

删除角色

typescript
async delete(notity: boolean = false): Promise<boolean> {
  if (!notity) {
    if (this.current.hasRelationAuth()) {
      this._sendIdentityChangeMsg(OperateType.Delete);
    }
    const res = await kernel.deleteIdentity({
      id: this.id,
    });
    if (!res.success) return false;
  }
  this.current.user.removeGivedIdentity([this.metadata.id]);
  this.current.identitys = this.current.identitys.filter((i) => i.key != this.key);
  return true;
}
  • 删除角色,并从系统中移除相关引用。

操作通知

typescript
override operates(): model.OperateModel[] {
  const operates: model.OperateModel[] = [];
  if (this.current.hasRelationAuth()) {
    operates.push(entityOperates.Update, fileOperates.Rename);
  }
  operates.push(...super.operates());
  return operates.sort((a, b) => (a.menus ? -10 : b.menus ? 10 : 0));
}
  • 定义角色支持的操作类型。

发送变更消息

typescript
async _sendIdentityChangeMsg(
  operate: OperateType,
  subTarget?: schema.XTarget,
): Promise<void> {
  await this.current.sendIdentityChangeMsg({
    operate,
    subTarget,
    identity: this.metadata,
    operater: this.current.user.metadata,
  });
}
  • 向系统发送角色变更通知。

三、权限管理接口与实现类

IAuthority 接口

typescript
export interface IAuthority extends IEntity<schema.XAuthority> {
  /** 加载归属组织 */
  space: IBelong;
  /** 拥有该权限的成员 */
  members: schema.XTarget[];
  /** 父级权限 */
  parent: IAuthority | undefined;
  /** 子级权限 */
  children: IAuthority[];
  /** 深加载 */
  deepLoad(reload?: boolean): Promise<void>;
  /** 加载成员用户实体 */
  loadMembers(reload?: boolean): Promise<schema.XTarget[]>;
  /** 创建权限 */
  create(data: schema.XAuthority, notity?: boolean): Promise<IAuthority | undefined>;
  /** 更新权限 */
  update(data: schema.XAuthority): Promise<boolean>;
  /** 删除权限 */
  delete(notity?: boolean): Promise<boolean>;
  /** 根据权限id查找权限实例 */
  findAuthById(authId: string, auth?: IAuthority): IAuthority | undefined;
  /** 查询权限id查找权限实例 */
  findAuthByOrgId(shareId: string): IAuthority[];
  /** 根据权限获取所有父级权限Id */
  loadParentAuthIds(authIds: string[]): string[];
  /** 判断是否拥有某些权限 */
  hasAuthoritys(authIds: string[]): boolean;
  /** 接受职权变更消息 */
  receiveAuthority(data: model.AuthorityOperateModel): Promise<boolean>;
}
  • 属性:

    • space: 归属组织。
    • members: 拥有该权限的成员列表。
    • parent: 父级权限。
    • children: 子级权限列表。
  • 方法:

    • deepLoad: 深度加载权限及其子权限。
    • loadMembers: 加载拥有该权限的成员。
    • create: 创建新的权限。
    • update: 更新权限信息。
    • delete: 删除权限。
    • findAuthById: 根据权限ID查找权限实例。
    • findAuthByOrgId: 根据组织ID查找权限实例。
    • loadParentAuthIds: 获取所有父级权限ID。
    • hasAuthoritys: 判断是否拥有某些权限。
    • receiveAuthority: 接收权限变更消息。

Authority 类

Authority 类实现了 IAuthority 接口,提供了权限管理的具体实现。IAuthority 接口定义了权限的基本属性和方法,用于描述权限在系统中的行为和功能。Authority 类实现了权限管理的核心功能,包括权限的创建、更新、删除、成员管理以及权限变更通知等操作。通过与系统内核的交互,确保权限管理操作的正确性和一致性。同时,通过递归和深度加载机制,支持复杂的权限层级结构管理。

typescript
export class Authority extends Entity<schema.XAuthority> implements IAuthority {
  constructor(_metadata: schema.XAuthority, _space: IBelong, _parent?: IAuthority) {
    super({ ..._metadata, typeName: '权限' }, []);
    this.space = _space;
    this.parent = _parent;
    for (const node of _metadata.nodes || []) {
      this.children.push(new Authority(node, _space, this));
    }
    this.directory = _space.directory;
  }
  • 构造函数: 接收权限的元数据、归属组织和父级权限,初始化权限对象。

方法实现

加载成员

typescript
async loadMembers(reload: boolean = false): Promise<schema.XTarget[]> {
  if (!this._memberLoaded || reload) {
    const res = await kernel.queryAuthorityTargets({
      id: this.id,
      subId: this.space.metadata.belongId,
    });
    if (res.success) {
      this._memberLoaded = true;
      this.members = res.data.result || [];
    }
  }
  return this.members;
}
  • 从后端加载拥有该权限的成员列表,支持重新加载。

创建权限

typescript
async create(
  data: schema.XAuthority,
  notity: boolean = false,
): Promise<IAuthority | undefined> {
  if (!notity) {
    const res = await kernel.createAuthority({ ...data, parentId: this.id });
    if (!res.success) return;
    data = res.data;
    await this.space.sendAuthorityChangeMsg(OperateType.Create, res.data);
  }
  const authority = new Authority(data, this.space, this);
  this.children.push(authority);
  return authority;
}
  • 创建新的权限,并通知系统。

更新权限

typescript
async update(data: schema.XAuthority): Promise<boolean> {
  data.id = this.id;
  data.parentId = this.metadata.parentId;
  data.name = data.name || this.name;
  data.code = data.code || this.code;
  data.icon = data.icon || this.metadata.icon;
  data.shareId = data.shareId || this.metadata.shareId;
  data.remark = data.remark || this.remark;
  const res = await kernel.updateAuthority(data);
  if (res.success && res.data?.id) {
    res.data.typeName = '权限';
    this.setMetadata(res.data);
    await this.space.sendAuthorityChangeMsg(OperateType.Update, res.data);
  }
  return res.success;
}
  • 更新权限的元数据信息,并通知系统。

删除权限

typescript
async delete(notity: boolean = false): Promise<boolean> {
  if (!notity) {
    const res = await kernel.deleteAuthority({
      id: this.id,
    });
    if (!res.success) return false;
    await this.space.sendAuthorityChangeMsg(OperateType.Delete, this.metadata);
  }
  if (this.parent) {
    this.parent.children = this.parent.children.filter((i) => i.key != this.key);
  }
  return true;
}
  • 删除权限,并从系统中移除相关引用。

深度加载

typescript
async deepLoad(reload: boolean = false): Promise<void> {
  await this.loadMembers(reload);
  await Promise.all(
    this.children.map(async (item) => {
      await item.deepLoad(reload);
    }),
  );
}
  • 深度加载权限及其所有子权限。

查找权限

typescript
findAuthById(authId: string, auth?: IAuthority): IAuthority | undefined {
  auth = auth || this.space.superAuth!;
  if (auth.id === authId) {
    return auth;
  } else {
    for (const item of auth.children) {
      const find = this.findAuthById(authId, item);
      if (find) {
        return find;
      }
    }
  }
}
  • 根据权限ID查找权限实例。

判断权限

typescript
hasAuthoritys(authIds: string[]): boolean {
  authIds = this.loadParentAuthIds(authIds);
  const orgIds = [this.metadata.belongId];
  if (this.metadata.shareId && this.metadata.shareId.length > 0) {
    orgIds.push(this.metadata.shareId);
  }
  return this.space.user.authenticate(orgIds, authIds);
}
  • 判断用户是否拥有某些权限。

接收权限变更消息

typescript
async receiveAuthority(data: model.AuthorityOperateModel): Promise<boolean> {
  let message = '';
  if (this.id == data.authority.parentId && data.operate == OperateType.Create) {
    message = `${data.operater?.name}新增权限【${data.authority.name}】.`;
    await this.create(data.authority, true);
  } else if (this.id == data.authority.id) {
    switch (data.operate) {
      case OperateType.Delete:
        message = `${data.operater?.name}将权限【${data.authority.name}】删除.`;
        await this.delete(true);
        break;
      case OperateType.Update:
        message = `${data.operater?.name}将权限【${data.authority.name}】信息更新.`;
        this.updateMetadata(data.authority);
        break;
      default:
        break;
    }
  } else {
    for (const child of this.children) {
      if (await child.receiveAuthority(data)) {
        return true;
      }
    }
  }
  if (message.length > 0) {
    if (data.operater?.id != this.space.user.id) {
      logger.info(message);
    }
    return true;
  }
  return false;
}
  • 接收并处理权限变更消息。

云原生应用研究院版权所有