jmms.protocols.scim.comm.crud.ScimUpdateInterceptor Maven / Gradle / Ivy
/*
* Copyright 2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jmms.protocols.scim.comm.crud;
import jmms.core.model.MetaField;
import jmms.protocols.scim.ScimConsts;
import jmms.protocols.scim.v2.Scim2Consts;
import jmms.protocols.scim.ScimMapping;
import jmms.protocols.scim.ScimModel;
import jmms.protocols.scim.v2.model.Scim2Patch;
import leap.core.annotation.Inject;
import leap.core.validation.BeanValidator;
import leap.lang.Strings;
import leap.lang.convert.Converts;
import leap.web.api.orm.ModelExecutionContext;
import leap.web.api.orm.ModelUpdateInterceptor;
import leap.web.exception.BadRequestException;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class ScimUpdateInterceptor extends ScimCrudInterceptor implements ModelUpdateInterceptor {
protected @Inject BeanValidator beanValidator;
@Override
public boolean handleUpdatePropertyNotFound(ModelExecutionContext context, String name, Object value, Set removes) {
if(isScimOperation(context)) {
removes.add(name);
return true;
}
return false;
}
@Override
public boolean handleUpdatePropertyReadonly(ModelExecutionContext context, String name, Object value, Set removes) {
if(isScimOperation(context)) {
removes.add(name);
return true;
}
return false;
}
@Override
public boolean processUpdateProperties(ModelExecutionContext context, Object id, Map o) {
ScimModel model = getScimModel(context);
if(null != model) {
if(model.getMajorVersion() < 2) {
processUpdatePropertiesV1(context, id, o, model);
}else {
processUpdatePropertiesV2(context, id, o, model);
}
}
return false;
}
protected void processUpdatePropertiesV1(ModelExecutionContext context, Object id, Map o, ScimModel model) {
Object meta = o.get(ScimConsts.META);
if(null != meta && meta instanceof Map) {
Object attributes = ((Map)meta).get(ScimConsts.ATTRIBUTES);
if(null != attributes && attributes instanceof List) {
for(Object a : ((List)attributes)) {
String attribute = a.toString();
if(!o.containsKey(attribute)) {
ScimMapping mapping = model.resolveMapping(attribute);
if(null != mapping) {
o.put(mapping.getFieldName(), null);
}else {
o.put(attribute, null);
}
}
}
}
}
o.remove(ScimConsts.META);
o.remove(ScimConsts.SCHEMAS);
model.mappingIn(o);
}
protected void processUpdatePropertiesV2(ModelExecutionContext context, Object id, Map o, ScimModel model) {
if(isJsonPatch(o)) {
Scim2Patch patch = Converts.convert(o, Scim2Patch.class);
for(Scim2Patch.Operation operation : patch.getOperations()) {
if(null == operation.op) {
throw new BadRequestException("Operation's op is required");
}
if(Strings.isEmpty(operation.path)) {
throw new BadRequestException("Operation's path is required");
}
if(operation.op == Scim2Patch.Op.ADD) {
throw new BadRequestException("The 'add' op not supported");
}
String property;
MetaField field = model.getEntity().getField(operation.path);
if(null != field) {
property = field.getName();
}else {
ScimMapping mapping = model.resolveMapping(operation.path);
if(null == mapping) {
throw new BadRequestException("Invalid operation path '" + operation.path + "'");
}
property = mapping.getFieldName();
}
Object value = operation.op == Scim2Patch.Op.REMOVE ? null : operation.value;
o.put(property, value);
}
o.remove(ScimConsts.SCHEMAS);
o.remove(Scim2Consts.OPERATIONS);
}else {
//model.mappingIn(o);
throw new BadRequestException("Invalid json patch body");
}
}
protected boolean isJsonPatch(Map o) {
Object schemas = o.get(ScimConsts.SCHEMAS);
if(null != schemas && schemas instanceof List) {
for(Object schema : ((List)schemas)){
if(Scim2Consts.SCHEMA_PATCH_OP.equals(schema)) {
return true;
}
}
return false;
}
Object operations = o.get(Scim2Consts.OPERATIONS);
if(null != operations && operations instanceof List) {
return true;
}
return false;
}
}