/** * Copyright (C) 2009 - 2014 Envidatec GmbH <info@envidatec.com> * * This file is part of JEAPI-SQL. * * JEAPI-SQL 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 in version 3. * * JEAPI-SQL 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 * JEAPI-SQL. If not, see <http://www.gnu.org/licenses/>. * * JEAPI-SQL is part of the OpenJEVis project, further project information are * published at <http://www.OpenJEVis.org/>. */ package org.jevis.commons.relationship; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jevis.api.JEVisAttribute; import org.jevis.api.JEVisClass; import org.jevis.api.JEVisClassRelationship; import org.jevis.api.JEVisConstants; import static org.jevis.api.JEVisConstants.ClassRelationship.*; import static org.jevis.api.JEVisConstants.ObjectRelationship.*; import org.jevis.api.JEVisException; import org.jevis.api.JEVisExceptionCodes; import org.jevis.api.JEVisObject; import org.jevis.api.JEVisRelationship; import org.jevis.api.JEVisSample; import org.jevis.api.JEVisUser; /** * This class helps handeling the Relationship * * TODO: this class belongs into he JEAp or JECommons * * @author Florian Simon <florian.simon@envidatec.com> */ public class RelationsManagment { static private Logger logger = LogManager.getLogger(RelationsManagment.class); /** * * @param user * @param object * @return */ public static boolean canRead(JEVisObject user, JEVisObject object) throws JEVisException { return checkMebershipForType(user, object, MEMBER_READ); } /** * * @param user * @param object * @return */ public static boolean canWrite(JEVisObject user, JEVisObject object) throws JEVisException { return checkMebershipForType(user, object, MEMBER_WRITE); } /** * * @param user * @param object * @return */ public static boolean canDelete(JEVisObject user, JEVisObject object) throws JEVisException { return checkMebershipForType(user, object, MEMBER_DELETE); } /** * * @param user * @param object * @return */ public static boolean canCreate(JEVisObject user, JEVisObject object) throws JEVisException { return checkMebershipForType(user, object, MEMBER_CREATE); } /** * * @param user * @param object * @return */ public static boolean canExcecude(JEVisObject user, JEVisObject object) throws JEVisException { return checkMebershipForType(user, object, MEMBER_EXECUTE); } /** * * @param user * @param object * @param type * @return */ public static boolean checkMebershipForType(JEVisObject user, JEVisObject object, int type) throws JEVisException { logger.trace("CheckMembership {} {} {}", user.getID(), object.getID(), type); try { return isSysAdmin(user); } catch (Exception ex) { System.out.println("Error while checking Sys Admin status: " + ex); logger.error("Error while checking Sys Admin status: {}", ex.getMessage());//ToDO there is some error here } logger.debug("checkMebershipForType: user: " + user.getID() + " object: " + object.getID() + " type: " + type); try { List<JEVisRelationship> userMemberships = getMembershipsRel(user); for (JEVisRelationship or : object.getRelationships()) { for (JEVisRelationship ur : userMemberships) { //is the Object Owner end the same as the user membership end logger.debug("object.owner[{}]==user.membership[{}]", ur.getEndObject().getID(), or.getEndObject().getID()); if (ur.getEndObject().getID().equals(or.getEndObject().getID())) { if (ur.isType(type)) { return true; } } } } } catch (NullPointerException ne) { logger.debug("Error while checking Memberships: {}", ne);//ToDO there is some error here } return false; } /** * * @param object * @return */ public static List<JEVisRelationship> getRelationByType(JEVisObject object, int type) throws JEVisException { List<JEVisRelationship> memberships = new ArrayList<JEVisRelationship>(); List<JEVisRelationship> objRel = object.getRelationships(); // logger.debug("Relationship.size: {}", objRel.size()); for (JEVisRelationship r : objRel) { if (r.isType(type)) { memberships.add(r); } } return memberships; } /** * * @param object * @return */ public static List<JEVisRelationship> getMembershipsRel(JEVisObject object) throws JEVisException { // logger.debug("getMembershipsRelations for {}", object.getID()); List<JEVisRelationship> memberships = new ArrayList<JEVisRelationship>(); List<JEVisRelationship> objRel = object.getRelationships(); // logger.debug("Relationship totals: {}", objRel.size()); for (JEVisRelationship r : objRel) { // logger.debug("Checking relationship: {}->{} [{}]", r.getStartObject().getID(), r.getEndObject().getID(), r.getType()); if (r.isType(MEMBER_READ) || r.isType(MEMBER_WRITE) || r.isType(MEMBER_EXECUTE) || r.isType(MEMBER_CREATE) || r.isType(MEMBER_DELETE)) { logger.debug("Found membership: {}", r); memberships.add(r); } } logger.debug("done searching"); return memberships; } /** * Is this still in use? also implementation seems wrong * * @param user * @return * @throws JEVisException */ public static boolean isSysAdmin(JEVisObject user) throws JEVisException { logger.trace("isSysAdmin {} ", user.getID()); JEVisAttribute sysAdminAtt = user.getAttribute("Sys Admin"); logger.trace("sysAdmin getValue"); JEVisSample value = sysAdminAtt.getLatestSample(); if (value == null || value.getValueAsBoolean() == false) { logger.trace("isSysAdmin {} {}", user.getID(), false); return false; } else { logger.trace("isSysAdmin {} {}", user.getID(), true); return value.getValueAsBoolean(); } // JEVisDataSourceSQL ds = (JEVisDataSourceSQL) user.getDataSource(); // return ds.getCurrentUserObject().isSysAdmin(); // if (user.getJEVisClass().getName().equals(USER)) { // JEVisAttribute sysAdmin = user.getAttribute(USER_SYS_ADMIN); // return sysAdmin.getLatestSample().getValueAsBoolean(); // } // return false; } public static boolean isParentRelationship(JEVisClass parent, JEVisClass child) throws JEVisException { if (child.getInheritance() != null) { return isParentRelationship(parent, child.getInheritance()); } for (JEVisClassRelationship rel : parent.getRelationships(OK_PARENT)) { if (rel.getOtherClass(parent).equals(child)) { return true; } } return false; } public static boolean isNestedRelationship(JEVisClass parent, JEVisClass child) throws JEVisException { if (child.getInheritance() != null) { return isNestedRelationship(parent, child.getInheritance()); } for (JEVisClassRelationship rel : parent.getRelationships(NESTED)) { if (rel.getOtherClass(parent).equals(child)) { return true; } } return false; } private static List<JEVisObject> getObjectOwner(JEVisObject obj, int type) { List<JEVisObject> owners = new ArrayList<JEVisObject>(); try { for (JEVisRelationship objOwner : obj.getRelationships(JEVisConstants.ObjectRelationship.OWNER, JEVisConstants.Direction.FORWARD)) { // System.out.println("objOwner: " + objOwner); try { for (JEVisRelationship groupMemeber : objOwner.getEndObject().getRelationships(type, JEVisConstants.Direction.BACKWARD)) { // System.out.println("groupMember: " + groupMemeber); owners.add(groupMemeber.getStartObject()); } } catch (JEVisException ex) { java.util.logging.Logger.getLogger(RelationsManagment.class.getName()).log(Level.SEVERE, null, ex); } } } catch (JEVisException ex) { java.util.logging.Logger.getLogger(RelationsManagment.class.getName()).log(Level.SEVERE, null, ex); } return owners; } /** * Checks if an membership relationship can be deleted by the current user. * * * @param rel JEVisRealtionship from the type Membership * @return true if the user can delte, thows an execption with the reason * when not. returns fals if the type is not an membership */ public static boolean canDeleteMembership(JEVisRelationship rel) { try { JEVisUser juser = rel.getStartObject().getDataSource().getCurrentUser(); // JEVisUser juser = new JEVisUser(currentUser); // List<JEVisObject> userMembership = juser.getUserGroups(); // System.out.println("Usergroups: " + Arrays.toString(userMembership.toArray())); if (rel.getType() == JEVisConstants.ObjectRelationship.MEMBER_CREATE || rel.getType() == JEVisConstants.ObjectRelationship.MEMBER_DELETE || rel.getType() == JEVisConstants.ObjectRelationship.MEMBER_EXECUTE || rel.getType() == JEVisConstants.ObjectRelationship.MEMBER_READ || rel.getType() == JEVisConstants.ObjectRelationship.MEMBER_WRITE) { // System.out.println("end Rel: " + rel.getEndObject()); // if (userMembership.contains(rel.getEndObject())) { // System.out.println("rule a63: " + rel); // return false; // } if (rel.getStartID() == juser.getUserID()) { throw new JEVisException("Unsifficent rights, user cannot delete its own user right", JEVisExceptionCodes.UNAUTHORIZED); } if (getObjectOwner(rel.getStartObject(), JEVisConstants.ObjectRelationship.MEMBER_DELETE).contains(juser.getUserObject())) { // System.out.println("is owner-owner: " + rel); return true; } } } catch (JEVisException ex) { java.util.logging.Logger.getLogger(RelationsManagment.class.getName()).log(Level.SEVERE, null, ex); } return false; } public static boolean canDeleteOwnership(JEVisRelationship rel) { try { JEVisUser currentUser = rel.getStartObject().getDataSource().getCurrentUser(); //Sys Admins can do everything for now if (currentUser.isSysAdmin()) { return true; } List<JEVisObject> groups = new ArrayList<>(); List<JEVisRelationship> rels = currentUser.getUserObject().getRelationships(JEVisConstants.ObjectRelationship.MEMBER_READ, JEVisConstants.Direction.FORWARD); for (JEVisRelationship re : rels) { if (!groups.contains(re.getEndObject())) { groups.add(re.getEndObject()); } } // System.out.println("My Groups: " + Arrays.toString(userGroups.toArray())); if (rel.getType() == JEVisConstants.ObjectRelationship.OWNER) { //get Owner Group JEVisObject relOwner = rel.getEndObject(); // JEVisObject relTarget = rel.getStartObject(); //User cannot delte his own permission if (groups.contains(relOwner)) { // System.out.println("cannot delete my own right"); return false; } //get Owner of this group for (JEVisRelationship relOwnerRel : relOwner.getRelationships(JEVisConstants.ObjectRelationship.OWNER, JEVisConstants.Direction.FORWARD)) { try { JEVisObject groupOwnerOwner = relOwnerRel.getEndObject(); // System.out.println("groupOwnerOwner: " + groupOwnerOwner.getName()); if (groups.contains(groupOwnerOwner)) { // System.out.println("im the owner of the owner so its ok"); return true; } } catch (Exception ex) { //TODO: remove this trycatch workaround which is nessasary because the user can see but not access relationshipts which are not for him } } } } catch (JEVisException ex) { java.util.logging.Logger.getLogger(RelationsManagment.class.getName()).log(Level.SEVERE, null, ex); } return false; } /** * Checks if the given users is allowed to delete the given relationship * * TODO: add handling for none Userrights relationships TODO: i it a goodway * to return only true and exeptions? * * @param user the current user using the JEAPI * @param rel JEVisRelationship to test for if it can be deleted * * @return true if the user has the permission to delete the * JEVisRelationship, throws JEVisException if false * @throws JEVisException */ public static boolean canDeleteRelationship(JEVisObject user, JEVisRelationship rel) throws JEVisException { // user = user.getDataSource().getCurrentUser(); if (rel.getType() == JEVisConstants.ObjectRelationship.MEMBER_CREATE || rel.getType() == JEVisConstants.ObjectRelationship.MEMBER_DELETE || rel.getType() == JEVisConstants.ObjectRelationship.MEMBER_EXECUTE || rel.getType() == JEVisConstants.ObjectRelationship.MEMBER_READ || rel.getType() == JEVisConstants.ObjectRelationship.MEMBER_WRITE) { return canDeleteMembership(rel); } else if (rel.getType() == JEVisConstants.ObjectRelationship.OWNER) { return canDeleteOwnership(rel); } else { //TODO: check the rules for other kind of relationships //Workaround for the alpha phase, normally the default is false return true; } } }