io.yawp.repository.shields.ShieldBase Maven / Gradle / Ivy
package io.yawp.repository.shields;
import io.yawp.commons.http.HttpException;
import io.yawp.commons.utils.FacadeUtils;
import io.yawp.repository.Feature;
import io.yawp.repository.IdRef;
import io.yawp.repository.ObjectHolder;
import io.yawp.repository.actions.ActionKey;
import io.yawp.repository.query.condition.BaseCondition;
import io.yawp.repository.query.condition.Condition;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public abstract class ShieldBase extends Feature {
private boolean allow = false;
private boolean lastAllow = false;
private ShieldConditions conditions;
private Class super T> facade;
private Class> endpointClazz;
private IdRef> id;
private List objects;
private Map params;
private ActionKey actionKey;
private Map actionMethods;
public abstract void always();
public abstract void defaults();
public abstract void index(IdRef> parentId);
public abstract void show(IdRef id);
public abstract void create(List objects);
public abstract void update(IdRef id, T object);
public abstract void destroy(IdRef id);
protected ShieldBase allow() {
return allow(true);
}
protected final ShieldBase allow(boolean allow) {
this.allow = this.allow || allow;
this.lastAllow = allow;
return this;
}
protected final ShieldBase where(String field, String operator, Object value) {
return where(Condition.c(field, operator, value));
}
protected final ShieldBase where(BaseCondition condition) {
if (!lastAllow) {
return this;
}
getConditions().where(condition);
return this;
}
protected ShieldBase facade(Class super T> facade) {
if (!lastAllow) {
return this;
}
this.facade = facade;
return this;
}
protected ShieldBase removeFacade() {
return facade(null);
}
protected final boolean isAction(Class>... actionClazzes) {
return isActionRoute() && Arrays.asList(actionClazzes).contains(currentActionClazz());
}
private boolean isActionRoute() {
return actionKey != null;
}
private Class> currentActionClazz() {
return yawp.getFeatures().get(endpointClazz).getActionClazz(actionKey);
}
protected final boolean requestHasAnyObject() {
return objects != null;
}
public final void protectIndex() {
always();
index(id);
throwNotFoundIfNotAllowed();
}
@SuppressWarnings("unchecked")
public final void protectShow() {
always();
show((IdRef) id);
throwNotFoundIfNotAllowed();
}
public final void protectCreate() {
always();
create(objects);
throwNotFoundIfNotAllowed();
applySetFacade();
verifyConditions();
throwForbiddenIfNotAllowed();
}
@SuppressWarnings("unchecked")
public final void protectUpdate() {
always();
update((IdRef) id, objects == null ? null : objects.get(0));
throwNotFoundIfNotAllowed();
applySetFacade();
verifyConditions();
throwForbiddenIfNotAllowed();
}
@SuppressWarnings("unchecked")
public final void protectDestroy() {
always();
destroy((IdRef) id);
throwNotFoundIfNotAllowed();
verifyConditions();
throwForbiddenIfNotAllowed();
}
public final void protectCustom() {
always();
protectedEachCustomAction();
throwNotFoundIfNotAllowed();
verifyConditions();
throwForbiddenIfNotAllowed();
}
private void throwNotFoundIfNotAllowed() {
if (!allow) {
throw new HttpException(404, "The resquest was not allowed by the endpoint shield " + getClass().getName());
}
}
private void throwForbiddenIfNotAllowed() {
if (!allow) {
throw new HttpException(403, "The resquest was not allowed by the endpoint shield " + getClass().getName());
}
}
@SuppressWarnings("unchecked")
private void applySetFacade() {
if (facade == null) {
return;
}
for (T object : objects) {
ObjectHolder objectHolder = new ObjectHolder(object);
IdRef existingObjectId = (IdRef) objectHolder.getId();
if (existingObjectId == null) {
FacadeUtils.set(object, facade);
continue;
}
FacadeUtils.set(object, existingObjectId.fetch(), facade);
}
}
@SuppressWarnings("unchecked")
public void applyGetFacade(Object object) {
if (facade == null) {
return;
}
FacadeUtils.get((T) object, facade);
}
public void setEndpointClazz(Class> endpointClazz) {
this.endpointClazz = endpointClazz;
}
public final void setId(IdRef> id) {
this.id = id;
}
@SuppressWarnings("unchecked")
public final void setObjects(List> objects) {
this.objects = (List) objects;
}
public BaseCondition getCondition() {
return conditions.getWhere();
}
public boolean hasCondition() {
return getConditions().getWhere() != null;
}
private ShieldConditions getConditions() {
if (conditions != null) {
return conditions;
}
conditions = new ShieldConditions(yawp, endpointClazz, id, objects);
return conditions;
}
private void verifyConditions() {
this.allow = getConditions().evaluate();
}
public boolean hasFacade() {
return facade != null;
}
public final void setParams(Map params) {
this.params = params;
}
public final void setActionKey(ActionKey actionKey) {
this.actionKey = actionKey;
}
public final void setActionMethods(Map actionMethods) {
this.actionMethods = actionMethods;
}
private void protectedEachCustomAction() {
if (!actionMethods.containsKey(actionKey)) {
defaults();
return;
}
Method method = actionMethods.get(actionKey);
invokeCustomActionShield(method);
}
private void invokeCustomActionShield(Method method) {
try {
Object[] arguments = ActionKey.getActionMethodParameters(method, id, params);
method.invoke(this, arguments);
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy