#created on: 4/11/2008 package org.openiaml.model.drools.rules.users #list any import classes here. import org.openiaml.model.drools.*; import org.openiaml.model.inference.*; import org.openiaml.model.model.*; import org.openiaml.model.model.impl.*; import org.openiaml.model.model.wires.*; import org.openiaml.model.model.visual.*; import org.openiaml.model.model.operations.*; import org.openiaml.model.model.scopes.*; import org.openiaml.model.model.components.*; import org.openiaml.model.model.users.*; #declare any global variables here global EcoreCreateElementsHelper handler; global DroolsInsertionQueue queue; global DroolsHelperFunctions functions; rule "When a session is protected by an AccessControlHandler with no login handler[type=user], add it" when session : Session ( ) ach : AccessControlHandler ( eContainer == session ) not (LoginHandler ( type == LoginHandlerTypes.USER, eContainer == session )) then LoginHandler lh = handler.generatedLoginHandler(ach, session); handler.setValue(lh, ComponentsPackage.eINSTANCE.getLoginHandler_Type(), LoginHandlerTypes.USER); handler.setName(lh, "role-based login handler"); queue.add(lh, drools); end rule "When a page is protected by an AccessControlHandler with no login handler[type=user], add it" when session : Session ( ) page : Page ( eContainer == session ) ach : AccessControlHandler ( eContainer == page ) not (LoginHandler ( type == LoginHandlerTypes.USER, eContainer == session )) # no AccessControlHandler within the session too (the above rule will create one) not (AccessControlHandler ( eContainer == session )) then LoginHandler lh = handler.generatedLoginHandler(ach, session); handler.setValue(lh, ComponentsPackage.eINSTANCE.getLoginHandler_Type(), LoginHandlerTypes.USER); handler.setName(lh, "role-based login handler"); queue.add(lh, drools); end rule "A page within a session protected by an ACH should have a 'permissions check' operation" when session : Session ( ) page : Page ( eContainer == session ) ach : AccessControlHandler ( eContainer == session ) not ( Operation ( eContainer == page, name == "permissions check" )) then CompositeOperation check = handler.generatedCompositeOperation(ach, page); handler.setName(check, "permissions check"); queue.add(check, drools); end rule "A page protected by an ACH should have a 'permissions check' operation" when page : Page ( ) ach : AccessControlHandler ( eContainer == page ) not ( Operation ( eContainer == page, name == "page permissions check" )) then CompositeOperation check = handler.generatedCompositeOperation(ach, page); handler.setName(check, "page permissions check"); queue.add(check, drools); end rule "Connect 'permissions check' up to the 'access' event of the session (ACH in session)" when session : Session ( ) page : Page ( eContainer == session ) ach : AccessControlHandler ( eContainer == session ) access : EventTrigger ( eContainer == page, name == 'access' ) check : Operation ( eContainer == page, name == "permissions check" ) not ( RunInstanceWire ( from == access, to == check )) then RunInstanceWire run = handler.generatedRunInstanceWire(ach, page, access, check); handler.setName(run, "run"); queue.add(run, drools); end rule "Connect 'permissions check' up to the 'access' event of the page (ACH in page)" when page : Page ( ) ach : AccessControlHandler ( eContainer == page ) access : EventTrigger ( eContainer == page, name == 'access' ) check : Operation ( eContainer == page, name == "page permissions check" ) not ( RunInstanceWire ( from == access, to == check )) then RunInstanceWire run = handler.generatedRunInstanceWire(ach, page, access, check); handler.setName(run, "run"); queue.add(run, drools); end rule "Connect fail wire from 'permissions check' to 'login page'" when root : InternetApplication ( ) session : Session ( eContainer == root ) page : Page ( eContainer == session ) ach : AccessControlHandler ( eContainer == session ) access : EventTrigger ( eContainer == page, name == 'access' ) check : CompositeOperation ( eContainer == page, name == "permissions check" ) lh : LoginHandler ( type == LoginHandlerTypes.USER, eContainer == session ) login : Page ( name == "login", eContainer == root ) not ( NavigateWire ( from == check, to == login, name == "fail" )) then NavigateWire nav = handler.generatedNavigateWire(ach, page, check, login); handler.setName(nav, "fail"); queue.add(nav, drools); end rule "User Stores contain a default role 'User'" when store : UserStore ( ) not ( Role ( name == "User", eContainer == store )) then Role user = handler.generatedRole(store, store); handler.setName(user, "User"); queue.add(user, drools); end rule "'User' role contains a default attribute 'email'" when store : UserStore ( ) user : Role ( eContainer == store, name == "User" ) not ( DomainAttribute ( name == "email", eContainer == user )) then DomainAttribute attr = handler.generatedDomainAttribute(user, user); handler.setName(attr, "email"); queue.add(attr, drools); end rule "'User' role contains a default attribute 'password'" when store : UserStore ( ) user : Role ( eContainer == store, name == "User" ) not ( DomainAttribute ( name == "password", eContainer == user )) then DomainAttribute attr = handler.generatedDomainAttribute(user, user); handler.setName(attr, "password"); queue.add(attr, drools); end # TODO can we refactor these from [User/Session] pairs into an abstract 'Scope'? /** * It doesn't matter whether the ACH is in the Session or in a Page; * the LoginHandler will always have the same input class (User role), * as the actual check logic is handled by the 'permissions check' * method. */ rule "A LoginHandler of type 'user' should have an incoming Role as a parameter, defaulting to User" when session : Session( ) login_handler : LoginHandler ( eContainer == session, type == LoginHandlerTypes.USER ) store : UserStore ( ) exists ( // it doesn't matter if the ACH is in the session or the page ach : AccessControlHandler ( eContainer == session || eval(functions.containingSession(ach).equals(session)) ) // the store contains either the roles or the permissions // referenced by the ACH; we only want one and obj : NamedElement ( eContainer == store ) and RequiresWire ( from == ach, to == obj ) ) user : Role ( eContainer == store, name == "User" ) # if there is already an incoming parameter wire, don't connect up User not (ParameterWire ( to == login_handler )) then ParameterWire param = handler.generatedParameterWire(login_handler, session, user, login_handler); queue.add(param, drools); end rule "Create 'check permissions' operation in AccessControlHandler" when ach : AccessControlHandler( ) not ( Operation ( name == "check permissions", eContainer == ach )) then PrimitiveOperation op = handler.generatedPrimitiveOperation(ach, ach); handler.setName(op, "check permissions"); queue.add(op, drools); end rule "Create contents of 'permissions check' operation in a Page (session)" when session : Session ( ) page : Page ( eContainer == session ) ach : AccessControlHandler ( eContainer == session ) check : CompositeOperation ( eContainer == page, name == "permissions check" ) ach_check : Operation ( eContainer == ach, name == "check permissions" ) not ( StartNode( eContainer == check )) then StartNode start = handler.generatedStartNode(check, check); queue.add(start, drools); # ok FinishNode finish = handler.generatedFinishNode(check, check); queue.add(finish, drools); # not ok CancelNode cancel = handler.generatedCancelNode(check, check); handler.setValue(cancel, OperationsPackage.eINSTANCE.getCancelNode_ExceptionText(), "Error: You do not have valid permissions. You may need to login."); queue.add(cancel, drools); # virtual operation call OperationCallNode opCall = handler.generatedOperationCallNode(check, check); handler.setName(opCall, "call permissions operation"); queue.add(opCall, drools); # run wire to this call RunInstanceWire run = handler.generatedRunInstanceWire(check, check, opCall, ach_check); handler.setName(run, "run"); queue.add(run, drools); ExecutionEdge edge1 = handler.generatedExecutionEdge(check, check); handler.setFrom(edge1, start); handler.setTo(edge1, opCall); queue.add(edge1, drools); # ok ExecutionEdge edge2 = handler.generatedExecutionEdge(check, check); handler.setFrom(edge2, opCall); handler.setTo(edge2, finish); queue.add(edge2, drools); # not ok ExecutionEdge edge3 = handler.generatedExecutionEdge(check, check); handler.setFrom(edge3, opCall); handler.setTo(edge3, cancel); queue.add(edge3, drools); end rule "Create contents of 'permissions check' operation in a Page (page)" when page : Page ( ) ach : AccessControlHandler ( eContainer == page ) check : CompositeOperation ( eContainer == page, name == "page permissions check" ) ach_check : Operation ( eContainer == ach, name == "check permissions" ) not ( StartNode( eContainer == check )) then StartNode start = handler.generatedStartNode(check, check); queue.add(start, drools); # ok FinishNode finish = handler.generatedFinishNode(check, check); queue.add(finish, drools); # not ok CancelNode cancel = handler.generatedCancelNode(check, check); handler.setValue(cancel, OperationsPackage.eINSTANCE.getCancelNode_ExceptionText(), "Error: You do not have valid permissions. You may need to login."); queue.add(cancel, drools); # virtual operation call OperationCallNode opCall = handler.generatedOperationCallNode(check, check); handler.setName(opCall, "call permissions operation"); queue.add(opCall, drools); # run wire to this call RunInstanceWire run = handler.generatedRunInstanceWire(check, check, opCall, ach_check); handler.setName(run, "run"); queue.add(run, drools); ExecutionEdge edge1 = handler.generatedExecutionEdge(check, check); handler.setFrom(edge1, start); handler.setTo(edge1, opCall); queue.add(edge1, drools); # ok ExecutionEdge edge2 = handler.generatedExecutionEdge(check, check); handler.setFrom(edge2, opCall); handler.setTo(edge2, finish); queue.add(edge2, drools); # not ok ExecutionEdge edge3 = handler.generatedExecutionEdge(check, check); handler.setFrom(edge3, opCall); handler.setTo(edge3, cancel); queue.add(edge3, drools); end rule "An AccessControlHandler that creates a LoginHandler should have the created 'current instance' as an incoming parameter (session)" when session : Session ( ) ach : AccessControlHandler ( eContainer == session ) login_handler : LoginHandler ( type == LoginHandlerTypes.USER, eContainer == session ) instance : UserInstance ( eContainer == session ) setWire : SetWire ( from == login_handler, to == instance ) not ( ParameterWire ( from == instance, to == ach )) then ParameterWire param = handler.generatedParameterWire(ach, ach, instance, ach); queue.add(param, drools); end rule "A separate AccessControlHandler that creates a LoginHandler should have the created 'current instance' as an incoming parameter (page within a session)" when session : Session ( ) page : Page ( eContainer == session ) ach : AccessControlHandler ( eContainer == page ) login_handler : LoginHandler ( type == LoginHandlerTypes.USER, eContainer == session ) instance : UserInstance ( eContainer == session ) setWire : SetWire ( from == login_handler, to == instance ) not ( ParameterWire ( from == instance, to == ach )) then ParameterWire param = handler.generatedParameterWire(ach, ach, instance, ach); queue.add(param, drools); end rule "Any role should extend the default User role" when store : UserStore ( ) user : Role ( name == "User", eContainer == store ) another : Role ( this != user ) not ( ExtendsWire ( from == another, to == user )) then ExtendsWire ext = handler.generatedExtendsWire(store, store, another, user); queue.add(ext, drools); end