Commit f8f8fcfa by Antti Tönkyrä

Base EJB layer implementation for association

1 parent 4726db02
package fi.codecrew.moya.beans;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import fi.codecrew.moya.enums.BortalApplication;
import fi.codecrew.moya.enums.NetworkAssociationStatus;
import fi.codecrew.moya.enums.apps.IAppPermission;
import fi.codecrew.moya.enums.apps.NetworkAssociationPermission;
import fi.codecrew.moya.facade.NetworkAssociationFacade;
import fi.codecrew.moya.model.ApplicationPermission;
import fi.codecrew.moya.model.EventUser;
import fi.codecrew.moya.model.GroupMembership;
import fi.codecrew.moya.model.NetworkAssociation;
import fi.codecrew.moya.model.Place;
import fi.codecrew.moya.model.Role;
/**
* Session Bean implementation class NetworkAssociationBean
*/
@Stateless
@LocalBean
public class NetworkAssociationBean implements NetworkAssociationBeanLocal {
@EJB
private UserBean userBean;
@EJB
private BarcodeBean barcodeBean;
@EJB
private RoleBean roleBean;
@EJB
private NetworkAssociationFacade networkAssociationFacade;
@EJB
private EventBean eventBean;
public NetworkAssociationBean() {}
@Override
public List<NetworkAssociation> getStatusByIPAndMAC(String ip, String mac) {
return networkAssociationFacade.findByIPAndMAC(eventBean.getCurrentEvent(), ip, mac);
}
@Override
public List<NetworkAssociation> getActiveAssociations(boolean activatePending) {
if(activatePending)
activatePendingAssociations();
return networkAssociationFacade.findByStatus(eventBean.getCurrentEvent(), NetworkAssociationStatus.ACTIVE);
}
@Override
public NetworkAssociation tryAssociate(String username, String password,
String ip, String mac, String code, boolean codeRequired)
throws Exception {
EventUser authUser = userBean.validateUser(username, password);
if(authUser == null)
throw new Exception("INVALID_USER_OR_PASSWORD");
NetworkAssociation association;
HashSet<IAppPermission> userPerms = new HashSet<>();
if (authUser.getUser().isSuperadmin()) {
// Iterate through all permissions & add
for (BortalApplication app : BortalApplication.values()) {
for (IAppPermission perm : app.getPermissions()) {
userPerms.add(perm);
}
}
} else {
for(Role r : userBean.localFindUsersRoles(authUser)) {
for(ApplicationPermission appPerm : r.getPermissions()) {
IAppPermission iap = appPerm.getPermission();
if(!userPerms.contains(iap)) {
userPerms.add(iap);
}
}
}
}
if(!userPerms.contains(NetworkAssociationPermission.CAN_ASSOCIATE))
throw new Exception("USER_HAS_NO_ASSOCIATE_PERMISSION");
if(codeRequired) {
Place place = resolvePlaceFromCode(code);
if(place == null) {
// This is a valid case when user has permissions that allow them to
// override any place requirements, effectively allowing for free
// associations without the need of a real place.
if(!userPerms.contains(NetworkAssociationPermission.OVERRIDE_PLACE_REQUIREMENT))
throw new Exception("INVALID_PLACECODE");
association = associate(authUser, userPerms, place, ip, mac);
} else {
if(place.getPlaceReserver().getUser().equals(authUser)) {
// This is the simple case when user goes to their own place
association = associate(authUser, userPerms, place, ip, mac);
} else {
// In this case, the user has probably shuffled their seats
// within their group
if(!userPerms.contains(NetworkAssociationPermission.CAN_SHUFFLE_IN_GROUP))
throw new Exception("INVALID_PLACECODE");
boolean userIsInGroup = false;
for(GroupMembership gm : place.getGroup().getMembers()) {
EventUser member = gm.getUser();
if(member != null && gm.getUser().equals(authUser)) {
userIsInGroup = true;
break;
}
}
if(!userIsInGroup)
throw new Exception("INVALID_PLACECODE");
association = associate(authUser, userPerms, place, ip, mac);
}
}
} else {
// Code was not required, this is often a case for WLAN
association = associate(authUser, userPerms, null, ip, mac);
}
return association;
}
private void activatePendingAssociations() {
List<NetworkAssociation> netAssocs = networkAssociationFacade.findByStatus(
eventBean.getCurrentEvent(), NetworkAssociationStatus.PENDING);
for(NetworkAssociation na : netAssocs) {
na.setStatus(NetworkAssociationStatus.ACTIVE);
na.setModifyTime(Calendar.getInstance());
}
}
private NetworkAssociation associate(EventUser authUser, HashSet<IAppPermission> userPerms,
Place place, String ip, String mac) {
// This tests the case where association request is still pending, we will not
// create new one but rather return an old one
List<NetworkAssociation> nas = networkAssociationFacade.findByIPAndMACAndStatus(
eventBean.getCurrentEvent(), ip, mac, NetworkAssociationStatus.PENDING);
if(nas.size() > 0)
return nas.get(0);
nas = networkAssociationFacade.findByIPAndMACAndStatus(
eventBean.getCurrentEvent(), ip, mac, NetworkAssociationStatus.ACTIVE);
if(nas.size() > 0)
return nas.get(0);
NetworkAssociation na = new NetworkAssociation();
na.setIP(ip);
na.setMAC(mac);
na.setPlace(place);
na.setEventUser(authUser);
na.setEvent(authUser.getEvent());
na.setStatus(NetworkAssociationStatus.PENDING);
List<NetworkAssociation> activeAssocs;
if(place == null) {
// When in this branch, we are doing an association which will never
// dis-associate things EXCEPT in the case where IP collision happens
// which usually is a result of network ops change...
activeAssocs = networkAssociationFacade.findActiveAssociationsByIP(
eventBean.getCurrentEvent(), ip);
for(NetworkAssociation activeAssoc : activeAssocs) {
activeAssoc.setModifyTime(Calendar.getInstance());
activeAssoc.setStatus(NetworkAssociationStatus.EXPIRED);
}
} else {
// In here we disassociate old associations from this place unless the user has many
// associations per place
if(!userPerms.contains(NetworkAssociationPermission.CAN_ASSOCIATE_MANY_PER_PLACE)) {
activeAssocs = networkAssociationFacade.findActiveAssociationsByPlace(place);
for(NetworkAssociation activeAssoc : activeAssocs) {
activeAssoc.setModifyTime(Calendar.getInstance());
activeAssoc.setStatus(NetworkAssociationStatus.EXPIRED);
}
}
}
// Finally persist the association and return
na = networkAssociationFacade.create(na);
return na;
}
private Place resolvePlaceFromCode(String code) {
if(code == null) return null;
return barcodeBean.getPlaceFromTextCode(code);
}
}
package fi.codecrew.moya.facade;
import java.util.List;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import fi.codecrew.moya.enums.NetworkAssociationStatus;
import fi.codecrew.moya.model.LanEvent;
import fi.codecrew.moya.model.NetworkAssociation;
import fi.codecrew.moya.model.NetworkAssociation_;
import fi.codecrew.moya.model.Place;
@Stateless
@LocalBean
public class NetworkAssociationFacade extends IntegerPkGenericFacade<NetworkAssociation> {
public NetworkAssociationFacade() { super(NetworkAssociation.class); }
public List<NetworkAssociation> findByIPAndMACAndStatus(LanEvent event, String ip, String mac, NetworkAssociationStatus nas) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<NetworkAssociation> cq = cb.createQuery(NetworkAssociation.class);
Root<NetworkAssociation> root = cq.from(NetworkAssociation.class);
cq.where(
cb.and(
cb.equal(root.get(NetworkAssociation_.event), event),
cb.equal(root.get(NetworkAssociation_.ip), ip),
cb.equal(root.get(NetworkAssociation_.mac), mac),
cb.equal(root.get(NetworkAssociation_.status), nas)
)
);
return getEm().createQuery(cq).getResultList();
}
public List<NetworkAssociation> findActiveAssociationsByIP(LanEvent event, String ip) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<NetworkAssociation> cq = cb.createQuery(NetworkAssociation.class);
Root<NetworkAssociation> root = cq.from(NetworkAssociation.class);
cq.where(
cb.and(
cb.equal(root.get(NetworkAssociation_.event), event),
cb.or(
cb.equal(root.get(NetworkAssociation_.status), NetworkAssociationStatus.PENDING),
cb.equal(root.get(NetworkAssociation_.status), NetworkAssociationStatus.ACTIVE)
),
cb.equal(root.get(NetworkAssociation_.ip), ip)
)
);
return getEm().createQuery(cq).getResultList();
}
public List<NetworkAssociation> findActiveAssociationsByPlace(Place place) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<NetworkAssociation> cq = cb.createQuery(NetworkAssociation.class);
Root<NetworkAssociation> root = cq.from(NetworkAssociation.class);
cq.where(
cb.and(
cb.or(
cb.equal(root.get(NetworkAssociation_.status), NetworkAssociationStatus.PENDING),
cb.equal(root.get(NetworkAssociation_.status), NetworkAssociationStatus.ACTIVE)
),
cb.equal(root.get(NetworkAssociation_.place), place)
)
);
return getEm().createQuery(cq).getResultList();
}
public List<NetworkAssociation> findByIPAndMAC(LanEvent event, String ip, String mac) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<NetworkAssociation> cq = cb.createQuery(NetworkAssociation.class);
Root<NetworkAssociation> root = cq.from(NetworkAssociation.class);
cq.where(
cb.and(
cb.equal(root.get(NetworkAssociation_.event), event),
cb.equal(root.get(NetworkAssociation_.ip), ip),
cb.equal(root.get(NetworkAssociation_.mac), mac)
)
);
return getEm().createQuery(cq).getResultList();
}
public List<NetworkAssociation> findByStatus(LanEvent event, NetworkAssociationStatus status) {
CriteriaBuilder cb = getEm().getCriteriaBuilder();
CriteriaQuery<NetworkAssociation> cq = cb.createQuery(NetworkAssociation.class);
Root<NetworkAssociation> root = cq.from(NetworkAssociation.class);
cq.where(
cb.and(
cb.equal(root.get(NetworkAssociation_.event), event),
cb.equal(root.get(NetworkAssociation_.status), status)
)
);
return getEm().createQuery(cq).getResultList();
}
}
package fi.codecrew.moya.beans;
import java.util.List;
import javax.ejb.Local;
import fi.codecrew.moya.model.NetworkAssociation;
@Local
public interface NetworkAssociationBeanLocal {
NetworkAssociation tryAssociate(String username, String password,
String ip, String mac, String code, boolean codeRequired)
throws Exception;
List<NetworkAssociation> getStatusByIPAndMAC(String ip, String mac);
List<NetworkAssociation> getActiveAssociations(boolean activatePending);
}
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!