247 lines
8.3 KiB
JavaScript
247 lines
8.3 KiB
JavaScript
"use strict";
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
const Feature_1 = require("../types/Feature");
|
||
const assert_1 = require("oak-domain/lib/utils/assert");
|
||
const lodash_1 = require("oak-domain/lib/utils/lodash");
|
||
const constant_1 = require("../constant/constant");
|
||
const relation_1 = require("oak-domain/lib/store/relation");
|
||
;
|
||
;
|
||
;
|
||
class Console extends Feature_1.Feature {
|
||
cache;
|
||
localStorage;
|
||
user;
|
||
userId;
|
||
isRoot;
|
||
consoleContext;
|
||
availMenus;
|
||
unsubFns;
|
||
initialize() {
|
||
this.unsubFns.push(this.user.subscribe(() => this.onUserChanged()));
|
||
}
|
||
saveContext(context) {
|
||
if (this.consoleContext !== context) {
|
||
this.consoleContext = context;
|
||
if (context) {
|
||
this.localStorage.save(constant_1.LOCAL_STORAGE_KEYS.consoleContext, context);
|
||
}
|
||
else {
|
||
this.localStorage.remove(constant_1.LOCAL_STORAGE_KEYS.consoleContext);
|
||
}
|
||
this.checkAvailMenus();
|
||
}
|
||
}
|
||
async onUserChanged() {
|
||
this.isRoot = this.user.isRoot();
|
||
const userId = this.user.getUserId(true);
|
||
if (userId !== this.userId) {
|
||
this.userId = userId;
|
||
}
|
||
if (this.userId && !this.isRoot) {
|
||
await this.cache.exec('loadRelations', {
|
||
entities: this.entities,
|
||
});
|
||
}
|
||
else if (!this.userId) {
|
||
this.saveContext(undefined);
|
||
return;
|
||
}
|
||
this.checkAvailMenus();
|
||
}
|
||
initAvailMenus() {
|
||
const schema = this.cache.getSchema();
|
||
this.availMenus = this.menus.map((menu) => {
|
||
const { destEntity, path, ...rest } = menu;
|
||
if (destEntity) {
|
||
let sourceEntity = destEntity;
|
||
if (path) {
|
||
const paths = path.split('.');
|
||
paths.forEach((ele) => {
|
||
const rel = (0, relation_1.judgeRelation)(schema, sourceEntity, ele);
|
||
if (rel === 2) {
|
||
sourceEntity = ele;
|
||
}
|
||
else if (typeof rel === 'string') {
|
||
sourceEntity = rel;
|
||
}
|
||
else {
|
||
(0, assert_1.assert)(rel instanceof Array);
|
||
sourceEntity = rel[0];
|
||
}
|
||
});
|
||
return {
|
||
destEntity,
|
||
path,
|
||
sourceEntity,
|
||
available: null,
|
||
...rest,
|
||
};
|
||
}
|
||
else {
|
||
return {
|
||
destEntity,
|
||
path,
|
||
sourceEntity,
|
||
available: null,
|
||
...rest,
|
||
};
|
||
}
|
||
}
|
||
return {
|
||
...menu,
|
||
available: null,
|
||
};
|
||
});
|
||
}
|
||
checkAvailMenus() {
|
||
if (this.consoleContext && this.userId) {
|
||
const { entity, entityId } = this.consoleContext;
|
||
// 这个不能放在constructor里面,因为this.menus是后初始化的
|
||
if (this.availMenus.length < this.menus.length) {
|
||
this.initAvailMenus();
|
||
}
|
||
const actionAuths = this.userId && !this.isRoot && this.cache.get('actionAuth', {
|
||
data: {
|
||
id: 1,
|
||
path: {
|
||
destEntity: 1,
|
||
sourceEntity: 1,
|
||
value: 1,
|
||
},
|
||
deActions: 1,
|
||
},
|
||
filter: {
|
||
relation: {
|
||
entity: entity,
|
||
$or: [
|
||
{
|
||
entityId,
|
||
},
|
||
{
|
||
entityId: {
|
||
$exists: false,
|
||
},
|
||
}
|
||
],
|
||
userRelation$relation: {
|
||
userId: this.userId
|
||
}
|
||
},
|
||
}
|
||
});
|
||
this.availMenus.forEach((menu) => {
|
||
let { destEntity, path, actions, sourceEntity } = menu;
|
||
let available = false;
|
||
switch (destEntity) {
|
||
// 如果是空字符串,表示对任何用户可见
|
||
case '': {
|
||
available = true;
|
||
break;
|
||
}
|
||
case 'userRelation': {
|
||
available = !!this.cache.checkOperation(destEntity, {
|
||
action: 'create',
|
||
data: {
|
||
entity: entity,
|
||
entityId
|
||
},
|
||
}, [
|
||
'relation'
|
||
]);
|
||
break;
|
||
}
|
||
case undefined: {
|
||
available = !!this.isRoot;
|
||
break;
|
||
}
|
||
default: {
|
||
(0, assert_1.assert)(actions?.length);
|
||
(0, assert_1.assert)(typeof path === 'string');
|
||
if (sourceEntity === entity) {
|
||
if (this.isRoot) {
|
||
available = true;
|
||
}
|
||
else if (this.userId) {
|
||
(0, assert_1.assert)(actionAuths);
|
||
available = !!actionAuths.find(actionAuth => (0, lodash_1.intersection)(actionAuth.deActions, actions).length > 0 && actionAuth.path.destEntity === destEntity && path === actionAuth.path.value);
|
||
}
|
||
}
|
||
else {
|
||
available = null;
|
||
}
|
||
}
|
||
}
|
||
menu.available = available;
|
||
});
|
||
}
|
||
else {
|
||
this.availMenus.forEach(ele => ele.available = null);
|
||
}
|
||
this.publish();
|
||
}
|
||
constructor(cache, localStorage, user, getEntityProjection) {
|
||
super();
|
||
this.cache = cache;
|
||
this.localStorage = localStorage;
|
||
this.user = user;
|
||
this.availMenus = [];
|
||
this.unsubFns = [];
|
||
this.initialize();
|
||
this.loadContext(getEntityProjection);
|
||
}
|
||
async loadContext(getEntityProjection) {
|
||
const context = await this.localStorage.load(constant_1.LOCAL_STORAGE_KEYS.consoleContext);
|
||
this.consoleContext = context;
|
||
if (this.consoleContext) {
|
||
const { entity, entityId } = this.consoleContext;
|
||
await this.cache.refresh(entity, {
|
||
data: getEntityProjection(entity),
|
||
filter: {
|
||
id: entityId,
|
||
},
|
||
});
|
||
this.checkAvailMenus();
|
||
}
|
||
}
|
||
setContext(entity, entityId) {
|
||
(0, assert_1.assert)(this.entities.includes(entity));
|
||
if (entity !== this.consoleContext?.entity || entityId !== this.consoleContext.entityId) {
|
||
this.saveContext({
|
||
entity,
|
||
entityId,
|
||
});
|
||
}
|
||
}
|
||
getContext() {
|
||
return this.consoleContext;
|
||
}
|
||
getAvailMenus() {
|
||
return this.availMenus.filter(ele => ele.available === true);
|
||
}
|
||
/**
|
||
* 检查当前url是否可以访问
|
||
* @param url
|
||
* @returns
|
||
* true: 可以访问
|
||
* false: 无权访问
|
||
* null: 上下文不匹配
|
||
* undefined: menu中没有此url
|
||
*/
|
||
checkUrlAvailable(url) {
|
||
let result = undefined;
|
||
for (const menu of this.availMenus) {
|
||
if (menu.url === url) {
|
||
if (menu.available) {
|
||
return true;
|
||
}
|
||
else {
|
||
result = menu.available;
|
||
}
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
}
|
||
exports.default = Console;
|