def execute(self): input = self.get_input() search_type = input.get('search_type') if search_type != 'sthpw/transaction_log': print("ERROR: this trigger can only be executed for transaction_logs") return project = Project.get() # Block admin project from syncing # NOTE: maybe need an option to enable this? if project.get_code() == 'admin': return log = input.get('sobject') transaction_code = log.get_value("code") # if this is a remote transaction, then do not create a job for it local_prefix = Config.get_value("install", "server") search = Search("sthpw/sync_server") search.add_filter("state", "online") servers = search.get_sobjects() #print("servers: ", len(servers)) # These are usually determined by the server entry #sync_mode = input.get('mode') #if not sync_mode or sync_mode == 'default': # sync_mode = 'xmlrpc' ## This will transaction into a "file" folder #sync_mode = "file" #file_mode = 'delayed' #file_mode = 'upload' # get some user info env = Environment.get() #user = env.get_user_name() #ticket = env.get_ticket() project_code = Project.get_project_code() from pyasm.security import AccessManager access_manager = AccessManager() for server in servers: # check security #if not self.check_security(server): # print("Transaction denied due to security restrictions") # continue server_code = server.get_code() # don't publish a transaction back to the original server if log.get_value("server_code") == server_code: continue # check project security rules = server.get_value("access_rules"); if not rules: rules = "<rules/>" access_manager.add_xml_rules(rules) # filter based on project code namespace = log.get_value("namespace") key1 = { 'code': namespace } key2 = { 'code': '*' } keys = [key1, key2] if not access_manager.check_access("project", keys, "allow", default="deny"): continue # filter based on transaction key """ keywords = log.get_value("kewords", no_exception=True) key1 = { 'keywords': keywords } key2 = { 'keywords': '*' } keys = [key1, key2] if not access_manager.check_access("transaction", keys, "allow", default="deny"): continue """ # filter out any specific rules from transaction itself from tactic.ui.sync import SyncFilter sync_filter = SyncFilter(rules=rules, transaction=log) sync_filter.execute() filtered_xml = sync_filter.get_filtered_xml() message = sync_filter.get_message() # create a new job entry job = SearchType.create("sthpw/sync_job") job.set_value("state", "pending") job.set_value("server_code", server_code) job.set_value("transaction_code", transaction_code) job.set_user() job.set_value("command", "tactic.command.TransactionQueueCmd") kwargs = { 'server': server.get_value("code"), 'transaction_code': transaction_code, 'project_code': project_code, #'file_mode': file_mode, #'sync_mode': sync_mode } job.set_json_value("data", kwargs) job.commit()
def get_display(my): div = DivWdg() div.add_class("spt_security") div.add_attr("id", "SecurityManagerWdg") div.add_attr("spt_class_name", Common.get_full_class_name(my) ) div.add_attr("spt_search_key", my.search_key) div.add_attr("spt_update", "true") project_div = DivWdg() project_div.add_color("background", "background") project_div.add_color("color", "color") project_div.add_style("padding: 10px") project_div.add_border() project_div.add_style("width: 300px") group = SearchKey.get_by_search_key(my.search_key) title = DivWdg() title.add_class("maq_search_bar") name = group.get_value("login_group") title.add("Global security settings for %s" % name) project_div.add(title) access_rules = group.get_xml_value("access_rules") access_manager = AccessManager() access_manager.add_xml_rules(access_rules) group = "builtin" global_default_access = "deny" list_div = DivWdg() list_div.add_style("color: #222") for item in permission_list: if item.get('group'): group_div = DivWdg() list_div.add(group_div) group_div.add_style("margin-top: 10px") group_div.add_style("font-weight: bold") group_div.add(item.get('group')) group_div.add("<hr/>") continue item_div = DivWdg() list_div.add(item_div) item_div.add_style("margin-top: 5px") key = item.get('key') item_default = item.get('default') if item_default: default_access = item_default else: default_access = global_default_access allowed = access_manager.check_access(group, key, "allow", default=default_access) checkbox = CheckboxWdg("rule") if allowed: checkbox.set_checked() checkbox.set_option("value", key) item_div.add(checkbox) item_div.add_style("color: #222") item_div.add(item.get('title') ) project_div.add(list_div) project_div.add("<hr>") #close_script = "spt.popup.close(bvr.src_el.getParent('.spt_popup'))" save_button = ActionButtonWdg(title="Save", tip="Save Security Settings") save_button.add_behavior( { "type": "click_up", "cbjs_action": "el=bvr.src_el.getParent('.spt_security');spt.panel.refresh(el);" } ) save_button.add_style("margin-left: auto") save_button.add_style("margin-right: auto") project_div.add(save_button) div.add(project_div) if my.update == "true": div.add(HtmlElement.br()) div.add(HtmlElement.b(my.description)) return div
def execute(my): log = my.log rules = my.rules # Give rules. Only notes will get through # we need heirarchical rules. This will ensure that only notes # for project/assets will pass # Here, the second one is much more difficult to do. rulesXXX = ''' <rule group='heirarchy' key='project/asset.sthpw/note' access='allow'/> <rule group='heirarchy' key="project/asset.sthpw/note['assigned','beth']" access='allow'/>" ''' access_manager = AccessManager() access_manager.add_xml_rules(rules) # filter out project namespace = log.get_value("namespace") key1 = { 'code': namespace } key2 = { 'code': '*' } keys = [key1, key2] if not access_manager.check_access("project", keys, "allow", default="deny"): my.filtered_xml = Xml() my.filtered_xml.read_string("<transaction/>") my.message = "Transaction prevented due to project restriction" return # filter the transaction against the security model xml = log.get_xml_value("transaction") my.filtered_xml = Xml() my.filtered_xml.create_doc("transaction") root2 = my.filtered_xml.get_root_node() nodes = xml.get_nodes("transaction/*") num_nodes = len(nodes) count = 0 for node in nodes: if Xml.get_node_name(node) == "sobject": search_type = xml.get_attribute(node, "search_type") parts = search_type.split("?") search_type = parts[0] # filter search types key1 = { 'code': search_type } key2 = { 'code': "*" } keys = [ key1, key2 ] if not access_manager.check_access("search_type", keys, "allow", default="deny"): continue # check hierachical rule parent_type = xml.get_attribute(node, "parent_type") key = "%s.%s" % (parent_type, search_type) my.filtered_xml.append_child(root2, node) count += 1 else: my.filtered_xml.append_child(root2, node) count += 1 if len(nodes) != 0 and len(my.filtered_xml.get_nodes("transaction/*")) == 0: my.message = "All actions filtered due to security restrictions (%s actions)" % num_nodes
def execute(my): log = my.log rules = my.rules # Give rules. Only notes will get through # we need heirarchical rules. This will ensure that only notes # for project/assets will pass # Here, the second one is much more difficult to do. rulesXXX = ''' <rule group='heirarchy' key='project/asset.sthpw/note' access='allow'/> <rule group='heirarchy' key="project/asset.sthpw/note['assigned','beth']" access='allow'/>" ''' access_manager = AccessManager() access_manager.add_xml_rules(rules) # filter out project namespace = log.get_value("namespace") key1 = {'code': namespace} key2 = {'code': '*'} keys = [key1, key2] if not access_manager.check_access( "project", keys, "allow", default="deny"): my.filtered_xml = Xml() my.filtered_xml.read_string("<transaction/>") my.message = "Transaction prevented due to project restriction" return # filter the transaction against the security model xml = log.get_xml_value("transaction") my.filtered_xml = Xml() my.filtered_xml.create_doc("transaction") root2 = my.filtered_xml.get_root_node() nodes = xml.get_nodes("transaction/*") num_nodes = len(nodes) count = 0 for node in nodes: if Xml.get_node_name(node) == "sobject": search_type = xml.get_attribute(node, "search_type") parts = search_type.split("?") search_type = parts[0] # filter search types key1 = {'code': search_type} key2 = {'code': "*"} keys = [key1, key2] if not access_manager.check_access( "search_type", keys, "allow", default="deny"): continue # check hierachical rule parent_type = xml.get_attribute(node, "parent_type") key = "%s.%s" % (parent_type, search_type) my.filtered_xml.append_child(root2, node) count += 1 else: my.filtered_xml.append_child(root2, node) count += 1 if len(nodes) != 0 and len( my.filtered_xml.get_nodes("transaction/*")) == 0: my.message = "All actions filtered due to security restrictions (%s actions)" % num_nodes
def get_display(my): div = DivWdg() div.add_class("spt_security") div.add_attr("id", "SecurityManagerWdg") div.add_attr("spt_class_name", Common.get_full_class_name(my) ) div.add_attr("spt_search_key", my.search_key) div.add_attr("spt_update", "true") project_div = DivWdg() project_div.add_color("background", "background") project_div.add_color("color", "color") project_div.add_style("padding: 10px") project_div.add_border() project_div.add_style("width: 300px") group = SearchKey.get_by_search_key(my.search_key) title = DivWdg() title.add_class("maq_search_bar") name = group.get_value("login_group") title.add("Global security settings for %s" % name) project_div.add(title) access_rules = group.get_xml_value("access_rules") access_manager = AccessManager() access_manager.add_xml_rules(access_rules) access_level = group.get_access_level() project_code = group.get_value('project_code') if project_code: project_codes = set(project_code) else: project_codes = set() xml = LoginGroup.get_default_access_rule(access_level, project_codes) access_manager.add_xml_rules(xml) group = "builtin" global_default_access = "deny" list_div = DivWdg() list_div.add_style("color: #222") for item in permission_list: if item.get('group'): group_div = DivWdg() list_div.add(group_div) group_div.add_style("margin-top: 10px") group_div.add_style("font-weight: bold") group_div.add(item.get('group')) group_div.add("<hr/>") continue item_div = DivWdg() list_div.add(item_div) item_div.add_style("margin-top: 5px") key = item.get('key') item_default = item.get('default') if item_default: default_access = item_default else: default_access = global_default_access allowed = access_manager.check_access(group, key, "allow", default=default_access) checkbox = CheckboxWdg("rule") if allowed: checkbox.set_checked() checkbox.set_option("value", key) item_div.add(checkbox) item_div.add_style("color: #222") item_div.add(item.get('title') ) project_div.add(list_div) project_div.add("<hr>") #close_script = "spt.popup.close(bvr.src_el.getParent('.spt_popup'))" save_button = ActionButtonWdg(title="Save", tip="Save Security Settings") save_button.add_behavior( { "type": "click_up", "cbjs_action": "el=bvr.src_el.getParent('.spt_security');spt.panel.refresh(el);" } ) save_button.add_style("margin-left: auto") save_button.add_style("margin-right: auto") project_div.add(save_button) div.add(project_div) if my.update == "true": div.add(HtmlElement.br()) div.add(HtmlElement.b(my.description)) return div
def get_share_wdg(my): div = DivWdg() div.add_style("padding: 20px") msg = '''<p>Before starting to work on a project that you are sharing, you should import the starting point.</p>''' div.add(msg) button = ActionButtonWdg(title="Import") div.add(button) button.add_behavior( { 'type': 'click_up', 'cbjs_action': ''' var class_name = 'tactic.ui.sync.SyncImportWdg'; var top = bvr.src_el.getParent(".spt_share_top"); var content = top.getElement(".spt_share_content"); spt.panel.load(content, class_name); //spt.panel.load_popup("Sync Import", class_name); ''' } ) msg = '''<p>This allows you to create a share for this project. This will allow you to share this project with others.</p>''' div.add(msg) button = ActionButtonWdg(title="Share") div.add(button) button.add_behavior( { 'type': 'click_up', 'cbjs_action': ''' var class_name = 'tactic.ui.sync.SyncServerAddWdg'; spt.panel.load_popup("Sync Share", class_name); ''' } ) title_wdg = DivWdg() div.add( title_wdg ) title_wdg.add( "Local" ) title_wdg.add_style("padding: 5px") title_wdg.add_color("background", "background", -10) title_wdg.add_border() title_wdg.add_style("margin: 5px -22px 10px -22px") local_code = Config.get_value("install", "server") or "" local_div = DivWdg() div.add(local_div) local_div.add_class("spt_share_item") local_div.add_attr("spt_server_code", local_code) local_div.add_class("hand") local_div.add(local_code) local_div.add_behavior( { 'type': 'click_up', 'cbjs_action': ''' var class_name = 'tactic.ui.startup.LocalItemWdg'; var top = bvr.src_el.getParent(".spt_share_top"); var content = top.getElement(".spt_share_content"); spt.panel.load(content, class_name); //spt.panel.load_popup("Sync Import", class_name); ''' } ) div.add("<br/>") search = Search("sthpw/sync_server") shares = search.get_sobjects() title_wdg = DivWdg() div.add( title_wdg ) title_wdg.add( "Share List" ) title_wdg.add_style("padding: 5px") title_wdg.add_color("background", "background", -10) title_wdg.add_border() title_wdg.add_style("margin: 5px -22px 10px -22px") shares_div = DivWdg() div.add(shares_div) shares_div.add_relay_behavior( { 'type': 'mouseup', 'bvr_match_class': 'spt_share_item', 'cbjs_action': ''' var server_code = bvr.src_el.getAttribute("spt_server_code"); var class_name = 'tactic.ui.startup.ShareItemWdg'; var kwargs = { server_code: server_code } var top = bvr.src_el.getParent(".spt_share_top"); var content = top.getElement(".spt_share_content"); spt.panel.load(content, class_name, kwargs); ''' } ) bgcolor = shares_div.get_color("background", -5) shares_div.add_relay_behavior( { 'type': 'mouseover', 'bvr_match_class': 'spt_share_item', 'bgcolor': bgcolor, 'cbjs_action': ''' bvr.src_el.setStyle("background", bvr.bgcolor); ''' } ) shares_div.add_relay_behavior( { 'type': 'mouseout', 'bvr_match_class': 'spt_share_item', 'cbjs_action': ''' bvr.src_el.setStyle("background", ""); ''' } ) from pyasm.security import AccessManager access_manager = AccessManager() project = Project.get() project_code = project.get_code() # add in a context menu menu = my.get_context_menu() menus = [menu.get_data()] menus_in = { 'SHARE_ITEM_CTX': menus, } SmartMenu.attach_smart_context_menu( shares_div, menus_in, False ) count = 0 for share in shares: # hide the shares that are not in this project rules = share.get_value("access_rules"); access_manager.add_xml_rules(rules) key1 = { 'code': project_code } key2 = { 'code': '*' } keys = [key1, key2] if not access_manager.check_access("project", keys, "allow", default="deny"): continue share_div = DivWdg() shares_div.add(share_div) share_div.add_class("spt_share_item") share_div.add_attr("spt_server_code", share.get_code()) share_div.add_class("hand") share_div.add(share.get_code()) share_div.add_attr("title", share.get_value("description") ) share_div.add_style("padding: 5px") base_dir = share.get_value("base_dir") if base_dir: base_div = SpanWdg() share_div.add(base_div) base_div.add_style("font-size: 0.9em") base_div.add_style("font-style: italic") base_div.add_style("opacity: 0.5") base_div.add(" (%s)" % base_dir) share_div.add_attr("spt_share_code", share.get_code() ) SmartMenu.assign_as_local_activator( share_div, 'SHARE_ITEM_CTX' ) count += 1 if not count: share_div = DivWdg() shares_div.add(share_div) share_div.add("<i>No shares</i>") share_div.add_style("padding: 5px") return div
def get_share_wdg(self): div = DivWdg() div.add_style("padding: 20px") msg = '''<p>Before starting to work on a project that you are sharing, you should import the starting point.</p>''' div.add(msg) button = ActionButtonWdg(title="Import") div.add(button) button.add_behavior( { 'type': 'click_up', 'cbjs_action': ''' var class_name = 'tactic.ui.sync.SyncImportWdg'; var top = bvr.src_el.getParent(".spt_share_top"); var content = top.getElement(".spt_share_content"); spt.panel.load(content, class_name); //spt.panel.load_popup("Sync Import", class_name); ''' } ) msg = '''<p>This allows you to create a share for this project. This will allow you to share this project with others.</p>''' div.add(msg) button = ActionButtonWdg(title="Share") div.add(button) button.add_behavior( { 'type': 'click_up', 'cbjs_action': ''' var class_name = 'tactic.ui.sync.SyncServerAddWdg'; spt.panel.load_popup("Sync Share", class_name); ''' } ) title_wdg = DivWdg() div.add( title_wdg ) title_wdg.add( "Local" ) title_wdg.add_style("padding: 5px") title_wdg.add_color("background", "background", -10) title_wdg.add_border() title_wdg.add_style("margin: 5px -22px 10px -22px") local_code = Config.get_value("install", "server") or "" local_div = DivWdg() div.add(local_div) local_div.add_class("spt_share_item") local_div.add_attr("spt_server_code", local_code) local_div.add_class("hand") local_div.add(local_code) local_div.add_behavior( { 'type': 'click_up', 'cbjs_action': ''' var class_name = 'tactic.ui.startup.LocalItemWdg'; var top = bvr.src_el.getParent(".spt_share_top"); var content = top.getElement(".spt_share_content"); spt.panel.load(content, class_name); //spt.panel.load_popup("Sync Import", class_name); ''' } ) div.add("<br/>") search = Search("sthpw/sync_server") shares = search.get_sobjects() title_wdg = DivWdg() div.add( title_wdg ) title_wdg.add( "Share List" ) title_wdg.add_style("padding: 5px") title_wdg.add_color("background", "background", -10) title_wdg.add_border() title_wdg.add_style("margin: 5px -22px 10px -22px") shares_div = DivWdg() div.add(shares_div) shares_div.add_relay_behavior( { 'type': 'mouseup', 'bvr_match_class': 'spt_share_item', 'cbjs_action': ''' var server_code = bvr.src_el.getAttribute("spt_server_code"); var class_name = 'tactic.ui.startup.ShareItemWdg'; var kwargs = { server_code: server_code } var top = bvr.src_el.getParent(".spt_share_top"); var content = top.getElement(".spt_share_content"); spt.panel.load(content, class_name, kwargs); ''' } ) bgcolor = shares_div.get_color("background", -5) shares_div.add_relay_behavior( { 'type': 'mouseover', 'bvr_match_class': 'spt_share_item', 'bgcolor': bgcolor, 'cbjs_action': ''' bvr.src_el.setStyle("background", bvr.bgcolor); ''' } ) shares_div.add_relay_behavior( { 'type': 'mouseout', 'bvr_match_class': 'spt_share_item', 'cbjs_action': ''' bvr.src_el.setStyle("background", ""); ''' } ) from pyasm.security import AccessManager access_manager = AccessManager() project = Project.get() project_code = project.get_code() # add in a context menu menu = self.get_context_menu() menus = [menu.get_data()] menus_in = { 'SHARE_ITEM_CTX': menus, } SmartMenu.attach_smart_context_menu( shares_div, menus_in, False ) count = 0 for share in shares: # hide the shares that are not in this project rules = share.get_value("access_rules"); access_manager.add_xml_rules(rules) key1 = { 'code': project_code } key2 = { 'code': '*' } keys = [key1, key2] if not access_manager.check_access("project", keys, "allow", default="deny"): continue share_div = DivWdg() shares_div.add(share_div) share_div.add_class("spt_share_item") share_div.add_attr("spt_server_code", share.get_code()) share_div.add_class("hand") share_div.add(share.get_code()) share_div.add_attr("title", share.get_value("description") ) share_div.add_style("padding: 5px") base_dir = share.get_value("base_dir") if base_dir: base_div = SpanWdg() share_div.add(base_div) base_div.add_style("font-size: 0.9em") base_div.add_style("font-style: italic") base_div.add_style("opacity: 0.5") base_div.add(" (%s)" % base_dir) share_div.add_attr("spt_share_code", share.get_code() ) SmartMenu.assign_as_local_activator( share_div, 'SHARE_ITEM_CTX' ) count += 1 if not count: share_div = DivWdg() shares_div.add(share_div) share_div.add("<i>No shares</i>") share_div.add_style("padding: 5px") return div
def execute(my): input = my.get_input() search_type = input.get('search_type') if search_type != 'sthpw/transaction_log': print "ERROR: this trigger can only be executed for transaction_logs" return project = Project.get() # Things done in the Admin project are not sync'd. # NOTE: maybe need an option to enable this? if project.get_code() == 'admin': return log = input.get('sobject') transaction_code = log.get_value("code") # if this is a remote transaction, then do not create a job for it local_prefix = Config.get_value("install", "server") search = Search("sthpw/sync_server") search.add_filter("state", "online") servers = search.get_sobjects() #print "servers: ", len(servers) mode = input.get('mode') if not mode or mode == 'default': mode = 'xmlrpc' # This will transaction into a "file" folder mode = "file" file_mode = 'upload' # get some user info env = Environment.get() #user = env.get_user_name() #ticket = env.get_ticket() project_code = Project.get_project_code() from pyasm.security import AccessManager access_manager = AccessManager() for server in servers: # FIXME # check security #if not my.check_security(server): # print "Transaction denied due to security restrictions" # continue server_code = server.get_code() # don't publish a transaction back to the original server if log.get_value("server_code") == server_code: continue # check project security rules = server.get_value("access_rules"); if not rules: rules = "<rules/>" access_manager.add_xml_rules(rules) namespace = log.get_value("namespace") key1 = { 'code': namespace } key2 = { 'code': '*' } keys = [key1, key2] if not access_manager.check_access("project", keys, "allow", default="deny"): continue from tactic.ui.sync import SyncFilter sync_filter = SyncFilter(rules=rules, transaction=log) sync_filter.execute() filtered_xml = sync_filter.get_filtered_xml() message = sync_filter.get_message() # create a new job entry job = SearchType.create("sthpw/sync_job") job.set_value("state", "pending") job.set_value("server_code", server_code) job.set_value("transaction_code", transaction_code) job.set_user() host = server.get_value("host") job.set_value("command", "tactic.command.TransactionQueueCmd") kwargs = { 'server': server.get_value("code"), 'transaction_code': transaction_code, 'file_mode': file_mode, 'project_code': project_code, 'mode': mode } job.set_json_value("data", kwargs) job.commit()