All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.yawp.repository.shields.ShieldBase Maven / Gradle / Ivy

There is a newer version: 2.08alpha
Show newest version
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 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 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