一、用户管理
用户抽象类实现,主要用于定义用户(Target)的行为和属性。:
typescript
export abstract class Target extends Team implements ITarget用户初始化
方法:
Target类的构造函数功能:初始化用户的基本属性(如会话、资源、目录等),并设置缓存机制。通过
setTimeout延迟加载用户数据,确保初始化过程的异步性。typescriptconstructor( _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, ); }
用户数据缓存
方法:
loadUserData、cacheUserData功能:
loadUserData:加载用户数据并订阅身份变更事件。cacheUserData:缓存用户数据,并在数据变化时通知其他用户。
typescriptasync 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; }
身份管理
方法:
loadIdentitys、createIdentity、sendIdentityChangeMsg功能:
loadIdentitys:从后端查询用户的身份,并缓存到identitys列表中。createIdentity:创建新的身份,并通知相关用户身份变更。sendIdentityChangeMsg:发送身份变更通知,确保所有相关用户及时收到更新。
typescriptasync 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功能:通知会话中的成员加入或退出,确保会话状态的一致性。
typescriptasync 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功能:将用户转换为组织分类,递归生成分类项,确保用户结构的完整性和一致性。
typescriptasync 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功能:处理身份变更事件,更新本地缓存并通知其他用户。
typescriptprivate 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;
}- 接收并处理权限变更消息。