mirror of
https://github.com/getrebuild/rebuild.git
synced 2024-09-20 07:25:54 +08:00
service obs / bizz view
This commit is contained in:
parent
3f7d515022
commit
cedc43b654
|
@ -90,7 +90,11 @@ public class EntityQueryFilter implements Filter, QueryFilter {
|
|||
@Override
|
||||
public String evaluate(Entity entity) {
|
||||
if (!EntityHelper.hasPrivilegesField(entity)) {
|
||||
return DENIED.evaluate(null);
|
||||
if (SecurityManager.isBizz(entity.getEntityCode())) {
|
||||
return ALLOWED.evaluate(null);
|
||||
} else {
|
||||
return DENIED.evaluate(null);
|
||||
}
|
||||
}
|
||||
|
||||
Privileges p = user.getOwningRole().getPrivileges(entity.getEntityCode());
|
||||
|
|
|
@ -21,6 +21,7 @@ package com.rebuild.server.bizz.privileges;
|
|||
import com.rebuild.server.bizz.RoleService;
|
||||
import com.rebuild.server.bizz.UserService;
|
||||
import com.rebuild.server.helper.cache.RecordOwningCache;
|
||||
import com.rebuild.server.metadata.EntityHelper;
|
||||
|
||||
import cn.devezhao.bizz.privileges.DepthEntry;
|
||||
import cn.devezhao.bizz.privileges.Permission;
|
||||
|
@ -220,6 +221,10 @@ public class SecurityManager {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (action == BizzPermission.READ && isBizz(entity)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Privileges priv = role.getPrivileges(entity);
|
||||
return priv.allowed(action);
|
||||
}
|
||||
|
@ -245,7 +250,11 @@ public class SecurityManager {
|
|||
return true;
|
||||
}
|
||||
|
||||
final int entity = target.getEntityCode();
|
||||
int entity = target.getEntityCode();
|
||||
|
||||
if (action == BizzPermission.READ && isBizz(entity)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Privileges priv = role.getPrivileges(entity);
|
||||
boolean allowed = priv.allowed(action);
|
||||
|
@ -335,4 +344,14 @@ public class SecurityManager {
|
|||
}
|
||||
return new EntityQueryFilter(theUser, action);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO 用户/部门全局可读
|
||||
*
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
public static boolean isBizz(int entity) {
|
||||
return entity == EntityHelper.User || entity == EntityHelper.Department;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ public abstract class CacheTemplate<V> {
|
|||
getCache().put(unityKey(key), value);
|
||||
}
|
||||
|
||||
public void evict(String key, V value) {
|
||||
public void evict(String key) {
|
||||
getCache().evict(unityKey(key));
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
package com.rebuild.server.helper.cache;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cache.CacheManager;
|
||||
|
||||
import com.rebuild.server.metadata.EntityHelper;
|
||||
|
@ -35,6 +37,8 @@ import cn.devezhao.persist4j.engine.ID;
|
|||
* @since 10/12/2018
|
||||
*/
|
||||
public class RecordOwningCache extends CacheTemplate<ID> {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(RecordOwningCache.class);
|
||||
|
||||
final private PersistManagerFactory aPMFactory;
|
||||
|
||||
|
@ -64,6 +68,7 @@ public class RecordOwningCache extends CacheTemplate<ID> {
|
|||
sql = String.format(sql, EntityHelper.owningUser, entity.getName(), entity.getPrimaryField().getName(), record.toLiteral());
|
||||
Object[] own = aPMFactory.createQuery(sql).unique();
|
||||
if (own == null) {
|
||||
LOG.warn("No record found : " + record);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -72,6 +77,13 @@ public class RecordOwningCache extends CacheTemplate<ID> {
|
|||
return ownUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param record
|
||||
*/
|
||||
public void cleanOwningUser(ID record) {
|
||||
evict(record.toLiteral());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String unityKey(Object key) {
|
||||
return "OU__" + super.unityKey(key);
|
||||
|
|
86
src/main/java/com/rebuild/server/service/AwareContext.java
Normal file
86
src/main/java/com/rebuild/server/service/AwareContext.java
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
rebuild - Building your system freely.
|
||||
Copyright (C) 2018 devezhao <zhaofang123@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.rebuild.server.service;
|
||||
|
||||
import cn.devezhao.bizz.privileges.Permission;
|
||||
import cn.devezhao.persist4j.Record;
|
||||
import cn.devezhao.persist4j.engine.ID;
|
||||
|
||||
/**
|
||||
* @author devezhao
|
||||
* @since 10/31/2018
|
||||
*/
|
||||
public class AwareContext {
|
||||
|
||||
// 操作人
|
||||
private ID editor;
|
||||
// 动作
|
||||
private Permission action;
|
||||
|
||||
// 记录 ID
|
||||
private ID recordId;
|
||||
// 记录(与记录 ID 两者二选一)
|
||||
private Record record;
|
||||
|
||||
private AwareContext(ID editor, Permission action, ID recordId) {
|
||||
super();
|
||||
this.editor = editor;
|
||||
this.action = action;
|
||||
this.recordId = recordId;
|
||||
}
|
||||
|
||||
private AwareContext(ID editor, Permission action, Record record) {
|
||||
super();
|
||||
this.editor = editor;
|
||||
this.action = action;
|
||||
this.record = record;
|
||||
}
|
||||
|
||||
public ID getEditor() {
|
||||
return editor;
|
||||
}
|
||||
|
||||
public Permission getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public ID getRecordId() {
|
||||
return recordId;
|
||||
}
|
||||
|
||||
public Record getRecord() {
|
||||
return record;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String astr = "{ Editor: %s, Action: %s, Record: %s }";
|
||||
return String.format(astr, getEditor(), getAction().getName(), getRecordId() != null ? getRecordId() : getRecord().getPrimary());
|
||||
}
|
||||
|
||||
// --
|
||||
|
||||
public static AwareContext valueOf(ID editor, Permission action, ID recordId) {
|
||||
return new AwareContext(editor, action, recordId);
|
||||
}
|
||||
|
||||
public static AwareContext valueOf(ID editor, Permission action, Record record) {
|
||||
return new AwareContext(editor, action, record);
|
||||
}
|
||||
}
|
93
src/main/java/com/rebuild/server/service/AwareObserver.java
Normal file
93
src/main/java/com/rebuild/server/service/AwareObserver.java
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
rebuild - Building your system freely.
|
||||
Copyright (C) 2018 devezhao <zhaofang123@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.rebuild.server.service;
|
||||
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import cn.devezhao.bizz.privileges.impl.BizzPermission;
|
||||
import cn.devezhao.commons.ThreadPool;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author devezhao
|
||||
* @since 10/31/2018
|
||||
*/
|
||||
public abstract class AwareObserver implements Observer {
|
||||
|
||||
protected static final Log LOG = LogFactory.getLog(AwareObserver.class);
|
||||
|
||||
@Override
|
||||
public void update(final Observable o, final Object arg) {
|
||||
final AwareContext ctx = (AwareContext) arg;
|
||||
if (isAsync()) {
|
||||
ThreadPool.exec(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
update(ctx);
|
||||
} catch (Exception ex) {
|
||||
LOG.error("AwareContext : " + ctx, ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
update(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
private void update(AwareContext ctx) {
|
||||
if (ctx.getAction() == BizzPermission.CREATE) {
|
||||
notifyCreate(ctx);
|
||||
} else if (ctx.getAction() == BizzPermission.UPDATE) {
|
||||
notifyUpdate(ctx);
|
||||
} else if (ctx.getAction() == BizzPermission.DELETE) {
|
||||
notifyDelete(ctx);
|
||||
} else if (ctx.getAction() == BizzPermission.ASSIGN) {
|
||||
notifyAssign(ctx);
|
||||
} else if (ctx.getAction() == BizzPermission.SHARE) {
|
||||
notifySahre(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否异步
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
abstract protected boolean isAsync();
|
||||
|
||||
public void notifyCreate(final AwareContext context) {
|
||||
}
|
||||
|
||||
public void notifyUpdate(final AwareContext context) {
|
||||
}
|
||||
|
||||
public void notifyDelete(final AwareContext context) {
|
||||
}
|
||||
|
||||
public void notifyAssign(final AwareContext context) {
|
||||
}
|
||||
|
||||
public void notifySahre(final AwareContext context) {
|
||||
}
|
||||
}
|
|
@ -18,6 +18,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
package com.rebuild.server.service;
|
||||
|
||||
import java.util.Observable;
|
||||
|
||||
import com.rebuild.server.Application;
|
||||
|
||||
import cn.devezhao.bizz.privileges.impl.BizzPermission;
|
||||
import cn.devezhao.persist4j.PersistManagerFactory;
|
||||
import cn.devezhao.persist4j.Record;
|
||||
import cn.devezhao.persist4j.engine.ID;
|
||||
|
@ -28,7 +33,7 @@ import cn.devezhao.persist4j.engine.ID;
|
|||
* @author zhaofang123@gmail.com
|
||||
* @since 05/21/2017
|
||||
*/
|
||||
public abstract class BaseService {
|
||||
public abstract class BaseService extends Observable {
|
||||
|
||||
final protected PersistManagerFactory aPMFactory;
|
||||
|
||||
|
@ -42,7 +47,9 @@ public abstract class BaseService {
|
|||
* @return
|
||||
*/
|
||||
public Record create(Record record) {
|
||||
return aPMFactory.createPersistManager().save(record);
|
||||
record = aPMFactory.createPersistManager().save(record);
|
||||
notifyObservers(AwareContext.valueOf(record.getEditor(), BizzPermission.CREATE, record));
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,7 +57,9 @@ public abstract class BaseService {
|
|||
* @return
|
||||
*/
|
||||
public Record update(Record record) {
|
||||
return aPMFactory.createPersistManager().update(record);
|
||||
record = aPMFactory.createPersistManager().update(record);
|
||||
notifyObservers(AwareContext.valueOf(record.getEditor(), BizzPermission.UPDATE, record));
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,10 +72,11 @@ public abstract class BaseService {
|
|||
|
||||
/**
|
||||
* @param recordId
|
||||
* @return 删除记录数量(包括关联的记录)
|
||||
* @return 删除记录数量。包括关联的记录,自定义实体都选择了 remove-link 级联模式,因此基本不会自动关联删除
|
||||
*/
|
||||
public int delete(ID recordId) {
|
||||
int affected = aPMFactory.createPersistManager().delete(recordId);
|
||||
notifyObservers(AwareContext.valueOf(Application.currentCallerUser(), BizzPermission.DELETE, recordId));
|
||||
return affected;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
rebuild - Building your system freely.
|
||||
Copyright (C) 2018 devezhao <zhaofang123@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.rebuild.server.service.base;
|
||||
|
||||
import com.rebuild.server.service.AwareObserver;
|
||||
|
||||
/**
|
||||
* TODO 记录审计日志
|
||||
*
|
||||
* @author devezhao
|
||||
* @since 10/31/2018
|
||||
*/
|
||||
public class AuditLoggingObserver extends AwareObserver {
|
||||
|
||||
@Override
|
||||
protected boolean isAsync() {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -33,6 +33,7 @@ import com.rebuild.server.bizz.privileges.User;
|
|||
import com.rebuild.server.helper.BulkTaskExecutor;
|
||||
import com.rebuild.server.metadata.EntityHelper;
|
||||
import com.rebuild.server.metadata.MetadataHelper;
|
||||
import com.rebuild.server.service.AwareContext;
|
||||
import com.rebuild.server.service.BaseService;
|
||||
|
||||
import cn.devezhao.bizz.privileges.Permission;
|
||||
|
@ -172,6 +173,8 @@ public class GeneralEntityService extends BaseService {
|
|||
affected += assign(id, to, null);
|
||||
}
|
||||
}
|
||||
|
||||
notifyObservers(AwareContext.valueOf(Application.currentCallerUser(), BizzPermission.ASSIGN, record));
|
||||
return affected;
|
||||
}
|
||||
|
||||
|
@ -215,6 +218,8 @@ public class GeneralEntityService extends BaseService {
|
|||
affected += share(id, to, null);
|
||||
}
|
||||
}
|
||||
|
||||
notifyObservers(AwareContext.valueOf(Application.currentCallerUser(), BizzPermission.SHARE, record));
|
||||
return affected;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<div class="col-6 pl-1 mb-2 btn-group J_action">
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"><i class="icon zmdi zmdi-more-vert"></i> 更多</button>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a class="dropdown-item J_delete2"><i class="icon zmdi zmdi-delete"></i> 删除</a>
|
||||
<a class="dropdown-item J_delete"><i class="icon zmdi zmdi-delete"></i> 删除</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -37,9 +37,10 @@
|
|||
<script src="${baseUrl}/assets/js/rb-view.jsx" type="text/babel"></script>
|
||||
<script type="text/babel">
|
||||
$(document).ready(function(){
|
||||
RbViewPage.init('${id}', [ '${entityLabel}', 'Department', '${entityIcon}'])
|
||||
RbViewPage.init('${id}', [ '${entityLabel}', 'Department', '${entityIcon}' ])
|
||||
if (rb.isAdminUser == false) $('.view-action').remove()
|
||||
|
||||
$('.J_delete2').click(function(){
|
||||
$('.J_delete').off('click').click(function(){
|
||||
$.get(rb.baseUrl + '/admin/bizuser/check-has-member?id=${id}', function(res){
|
||||
if (res.data == 0){
|
||||
rb.alert('此部门可以被安全的删除', '删除部门', { type: 'danger', confirmText: '删除', confirm: deleteDept })
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
<div class="col-6 pl-1 mb-2 btn-group J_action">
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown"><i class="icon zmdi zmdi-more-vert"></i> 更多</button>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a class="dropdown-item J_delete2"><i class="icon zmdi zmdi-delete"></i> 删除</a>
|
||||
<a class="dropdown-item J_delete"><i class="icon zmdi zmdi-delete"></i> 删除</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item J_changeDept"><i class="icon zmdi zmdi-accounts"></i> 改变部门</a>
|
||||
<a class="dropdown-item J_changeRole"><i class="icon zmdi zmdi-lock"></i> 改变角色</a>
|
||||
|
@ -40,9 +40,10 @@
|
|||
<script src="${baseUrl}/assets/js/rb-view.jsx" type="text/babel"></script>
|
||||
<script type="text/babel">
|
||||
$(document).ready(function(){
|
||||
RbViewPage.init('${id}', [ '${entityLabel}', 'User', '${entityIcon}'])
|
||||
RbViewPage.init('${id}', [ '${entityLabel}', 'User', '${entityIcon}' ])
|
||||
if (rb.isAdminUser == false) $('.view-action').remove()
|
||||
|
||||
$('.J_delete2').click(function(){
|
||||
$('.J_delete').off('click').click(function(){
|
||||
rb.alert('我们建议你停用用户,而非删除', '删除用户', { confirmText: '停用', confirm: function(){
|
||||
let _data = {isDisabled: true }
|
||||
_data.metadata = { entity: 'User', id: '${id}' }
|
||||
|
|
Loading…
Reference in a new issue