%!
import logging
# uiHelper requires splunk.util to be imported.
import splunk.util
from splunk import auth
#needed for views page
import lxml.etree as et
from xml.sax.saxutils import quoteattr
import re
import splunk.entity as en
from splunk.appserver.mrsparkle.lib import util, cached
from splunk.appserver.mrsparkle.lib.eai import cpQuoteEntity
from future.moves.urllib import parse as urllib_parse
import time
logger = logging.getLogger('splunk.appserver.templates.admin._helpers')
isLite = util.isLite()
isCloud = util.isCloud()
isAdmin = False
isDMCDisabled = True
if isLite:
entity = en.getEntity('/authentication', 'current-context', namespace=splunk.getDefault('namespace'))
roles = entity.get('roles')
if roles:
if 'admin' in roles:
isAdmin = True
if isCloud:
try:
dmc_settings = en.getEntity('dmc-conf/settings', 'settings')
isDMCDisabled = splunk.util.normalizeBoolean(dmc_settings['disabled'])
except splunk.RESTException as e:
logger.error('Failed to fetch DMC settings to verify status')
logger.exception(e)
except KeyError as e:
logger.error('Failed to fetch DMC disabled status')
logger.exception(e)
except ValueError as e:
logger.error('Failed to parse disabled status')
logger.exception(e)
sharing_names = {'user' : _("Private"),
'app' : _("App"),
'global' : _("Global"),
'system' : _("Global")}
action_names = {'disable' : _("Disable"),
'enable' : _("Enable"),
'remove' : _("Delete"),
'quarantine' : _("Quarantine"),
'unquarantine' : _("Unquarantine"),
'unembed' : _("Disable Embed")}
year = time.strftime('%Y')
%>
<%def name="renderContextSwitcher()">
<%
from lib.util import current_url_path
from future.moves.urllib import parse as urllib_parse
from future.moves.urllib.parse import urlencode
showAppSwitcher = True
url = current_url_path(include_qs=True)
urlParts = url.split("?")
path = urlParts[0]
try:
qstring = urlParts[1]
except IndexError:
qstring = ""
try:
qsdict = urllib_parse.parse_qs(qstring)
except Exception as e:
qsdict = {}
"""
logger.debug("\n\n")
logger.debug("urlParts ['path','qs'] :: %s" % urlParts)
logger.debug("qsdict: %s" % qsdict)
logger.debug("\n\n")
"""
pathParts = path.split("/")
# show the switcher, or just the label?
# check if this is the permissions page.
if pathParts[3] == "permissions":
showAppSwitcher = False
namespace = pathParts[4]
else:
namespace = pathParts[3]
try:
section = pathParts[4]
if section in ["apps","accesscontrols","authoverview","authentication","distsearch","data","datainputstats","control","forwardreceive","licensestats","systemsettings"]:
showAppSwitcher = False
except Exception as e:
pass
# determine if this is an edit, if so disable the switcher.
# the values for qsdict are in a list
actionList = qsdict.get("action")
if actionList != None:
if qsdict.get("action")[0] == "edit":
showAppSwitcher = False
if showAppSwitcher:
# build the list of apps for the context switcher.
# set the namespace path part to %s
pathParts[3] = "%s"
strReplUrl = "/".join(pathParts)
if len(qstring) > 0:
qstring = "?%s" % qstring
appOptionList = [ { 'label': '(All Apps)', 'uri': (strReplUrl % '-') + qstring , 'id': '' }, { 'divider': 'actionsMenuDivider' } ]
try:
appList = en.getEntities("apps/local", search=['disabled=false','visible=true'], count=-1)
except Exception as e:
logger.error("exception accessing apps local endpoint.")
logger.error("Exception string e: %s" % e)
try:
manageableAppOptionList = [ {'label': '%s' % ( appList[x].get('label', appList[x].name) ), 'uri': (strReplUrl % appList[x].name ) + qstring } for x in appList ]
appOptionList.extend( manageableAppOptionList )
except Exception as e:
logger.error("exception building appOptionList.")
logger.error("Exception string e: %s" % e)
endif
%>
% if showAppSwitcher:
<%
if namespace == "-":
switcherActivatorLabel = "All Apps"
else:
switcherActivatorLabel = APP['label']
endif
%>
${_(switcherActivatorLabel)}
% else:
${_(APP['label'])} » \
% endif
%def>
<%def name="renderBreadcrumbs(breadcrumb)">
<%
from lib.util import current_url_path
from future.moves.urllib import parse as urllib_parse
from future.moves.urllib.parse import urlencode
url = current_url_path(include_qs=True)
urlParts = url.split("?")
path = urlParts[0]
try:
qstring = urlParts[1]
except IndexError:
qstring = ""
try:
qsdict = urllib_parse.parse_qs(qstring)
except Exception as e:
qsdict = {}
if endpoint_path and endpoint_path.startswith("data/inputs/tcp/raw"):
hostAndPort = resolveTcpInputName(breadcrumb[-1][0])
if hostAndPort['host'] is not None:
pageTitle = _("%(port)s (restricted to host %(host)s)") % {'port' : hostAndPort['port'], 'host' : hostAndPort['host']}
else:
pageTitle = hostAndPort['port']
endif
else:
if breadcrumb:
pageTitle = breadcrumb[-1][0]
endif
%>
% if breadcrumb:
${pageTitle|h}
% endif
% if breadcrumb and len(breadcrumb) > 2:
\
% for i, (title, url) in enumerate(breadcrumb):
<%
if endpoint_path and endpoint_path.startswith("data/inputs/tcp/raw"):
title = resolveTcpInputName(title)['port']
endif
%>
<% made_url = None %>
% if url :
<% made_url = make_url(url) %>
% endif
% if made_url and (re.search('/manager/?\w*/?$', made_url) == None) :
${_(title) | h} \
» \
% elif not url:
${_(title)|h} \
% endif
% endfor
\
% endif
%def>
<%def name="message(content=None, level='info', msg_obj=None)">
% if msg_obj:
% endif
% if content:
% if isinstance(content, splunk.util.string_type):
- ${content|h}
% elif isinstance(content, list):
% for x in content:
- ${x|h}
% endfor
% else:
- ${_('Invalid message type:')} ${content|h}
% endif
% endif
%def>
<%def name="generateFormRow(element, eaiAttributes, form_defaults)">
<%
widget = element['type'] if 'type' in element else 'textfield'
widgetstyle = ''
depends = element.get('hideUnlessFieldSet')
hidetype = 'hideUnlessFieldSet' if 'hideUnlessFieldSet' in element else None
if not hidetype:
hidetype = 'nullUnlessFieldSet' if 'nullUnlessFieldSet' in element else None
if hidetype:
depends = element[hidetype]
depends = depends if isinstance(depends, list) else [ depends ]
for depend in depends:
if not form_defaults.get(depend, ''):
if hidetype == 'nullUnlessFieldSet':
widget = 'hidden'
else:
widgetstyle = 'style="display: none"'
%>
<%include file="/admin/widgets/${widget}.html" args="element=element, eaiAttributes=eaiAttributes, widgetstyle=widgetstyle" />
%def>
<%def name="makeSortHeading(elementLabel, elementName, kwargs)">
<%
sort_key = kwargs.get("sort_key", None)
sort_dir = kwargs.get("sort_dir", None)
import copy
qs = copy.deepcopy(kwargs)
qs['sort_key'] = elementName
isSorted = (sort_key == elementName)
if sort_dir == None :
sort_dir = "asc"
sort_class = "splSortNone"
elif sort_dir == "desc":
sort_dir = "asc"
sort_class = "splSortDesc"
else:
sort_dir = "desc"
sort_class = "splSortAsc"
qs['sort_dir'] = sort_dir
%>
${elementLabel|h}
% if isSorted:
% else :
% endif
%def>
<%!
## global col count var
countCols = 0
countRows = 0
%>
<%def name="resolveTcpInputName(name)">
<%
if name:
nameParts = name.split(":")
if len(nameParts) == 2:
return {'host' : nameParts[0], 'port' : nameParts[1]}
endif
return {'host' : None, 'port' : name}
%>
%def>
<%def name="genListRows(namespace, uiHelper, entities, endpoint_path, showAdvancedEdit=False, kwargs=None, newLabel=_('New'))">
<%
global countCols
global countRows
isAppList = True if endpoint_path == 'apps/local' else False
isRolesList = True if endpoint_path == 'authorization/roles' else False
isForwardingServer = True if endpoint_path == 'data/outputs/tcp/server' else False
isDeploymentserverclass = True if endpoint_path == 'deployment/serverclass' else False
isDistributedSearchPeers = True if endpoint_path == 'search/distributed/peers' else False
isSavedsearches = True if endpoint_path == 'saved/searches' else False
isLDAP = True if endpoint_path == 'authentication/providers/LDAP' else False
isViews = True if endpoint_path == 'data/ui/views' else False
isClonable = False if endpoint_path in ['admin/Duo-MFA', 'data/inputs/monitor', 'data/outputs/tcp/group','data/inputs/win-event-log-collections','data/lookup-table-files','data/indexes','data/props/extractions', 'authorization/roles', 'search/distributed/peers'] or endpoint_path.startswith('deployment/server/setup/data/inputs') else True
if isLite and isSavedsearches:
isClonable = False
isTcpInput = True if endpoint_path == 'data/inputs/tcp/raw' else False
isEnablable = True
isForwardedInput = True if endpoint_path.startswith('deployment/server/setup/data/inputs') else False
showEnabledColumn = False if uiHelper.get('hideEnabledColumn') else True
showPermissionsColumn = False if uiHelper.get('hidePermissionsColumn') else True
showActionsColumn = False if uiHelper.get('hideActionsColumn') else True
showAppContext = True if splunk.util.normalizeBoolean(uiHelper.get("showAppContext", "")) else False
displayNameField = uiHelper.get('displayNameField')
%>
<%
from lib.eai import cpQuoteEntity
from lib.util import current_url_path, strip_url
from future.moves.urllib import parse as urllib_parse
countRows = 0
countCols = 0
url = current_url_path(include_qs=True)
urlParts = url.split("?")
try:
qstring = urlParts[1]
except IndexError:
qstring = ""
try:
qsdict = urllib_parse.parse_qs(qstring)
except Exception as e:
qsdict = {}
try:
hasCreateLink = list(filter((lambda x: x[0] == 'create'), entities.links))
except:
hasCreateLink = False
%>
<%def name="genDataCells(elements, entity_endpoint_path, headerRow=False)">
<%
global countCols
global countRows
%>
% for element in elements:
<%
showSummarizationColumn = True if isSavedsearches and element.get("elementName") == "name" else False
%>
% if headerRow:
% if "list" in element.get("showInView", []):
% if "elements" in element:
<%call expr="genDataCells(element['elements'], entity_endpoint_path, headerRow)"/>
% endif
<%
elementLabel = None
sortable = splunk.util.normalizeBoolean(element.get('labelListSortable', 'True'))
if "labelList" in element:
elementLabel = _(element["labelList"])
elif "label" in element:
elementLabel = _(element["label"])
elif element["type"] != "fieldset":
elementLabel = element["elementName"]
else:
continue
%>
% if showSummarizationColumn:
<% countCols += 1 %>
|
% endif
<% countCols += 1 %>
% if sortable:
<%call expr="makeSortHeading(elementLabel, element['elementName'], kwargs)"/>
% else:
${_(elementLabel)}
% endif
|
% endif
% else:
% if "list" in element.get("showInView", []):
% if "elements" in element:
<%call expr="genDataCells(element['elements'], entity_endpoint_path, headerRow)"/>
% endif
% if element.get("type") != "fieldset":
% if showSummarizationColumn:
<% countCols += 1 %>
% if entity.get('auto_summarize','') == '1':
<% qs={'savedsearch': cpQuoteEntity(entity.name, urlquote=False)} %>
% endif
|
% endif
<% countCols += 1 %>
% if element.get("elementName") == "name":
<%
qs = {'action':'edit'}
if entity['eai:acl']['app']:
qs['ns'] = entity['eai:acl']['app']
for key in kwargs:
if key in ('pwnr', 'ns', 'search', 'offset', 'count', 'sort_key', 'sort_dir') or key.lower().startswith('api.'):
qs['f_'+key] = kwargs[key]
list_links = list(filter((lambda x: x[0] == 'list'), entity.links))
if isLite and isSavedsearches:
list_links = False
%>
<%
entityName = entity.name
if isTcpInput:
entityName = resolveTcpInputName(entityName)['port']
endif
%>
% if list_links and not isAppList and not isForwardingServer:
% if isForwardedInput and entity['eai:acl']['app']:
<% qs = {'uri': '/services/' + entity_endpoint_path + '/' + urllib_parse.quote(entity.name.encode('utf8')).replace('\\','%5C').replace('/','%2F'), 'action': 'edit', 'app_name': entity['eai:acl']['app']} %>
% elif entity_endpoint_path == 'saved/searches':
<% qs = {'app': entity['eai:acl'].get('app'), 'owner': entity.owner, 'search': '"' + cpQuoteEntity(entity.name, urlquote=False) + '"', 'uri':list_links[0][1], 'action':'edit'} %>
% else:
<% qs['uri'] = list_links[0][1] %>
% endif
${entityName | h}
% else:
${entityName | h}
% endif
% else:
<%
# apply any transformations defined in uiHelper
value = entity.get(element['elementName'], '')
processed_value = None
if 'processValueList' in element:
try:
processed_value = eval(element['processValueList'], locals())
except Exception as e:
logger.error('uiHelper processValueList operator failed for endpoint_path=%s elementName=%s: %s' % (endpoint_path, element['elementName'], str(e)))
processed_value = '[PROCESSING ERROR]'
%>
% if 'showRSSLink' in element:
% if value == "1":
% endif
% elif 'showAlertsLink' in element:
% if len(value)>0:
<%
alerts_id = None
for link in entity.links:
if link[0]=='alerts':
alerts_id = urllib_parse.quote_plus(link[1])
break
%>
% if alerts_id:
${i18n.format_number(int(value))|h}
% else:
${i18n.format_number(int(value))|h}
% endif
% else:
${_('0')}
% endif
% elif processed_value is None:
${value | h}
% else:
% if endpoint_path.startswith('deployment/server/setup/data/inputs') and (element.get("elementName") == 'eai:acl.app') and processed_value != 'N/A':
${processed_value|h}
% else:
${processed_value|h}
% endif
% endif
<%
update_link = list(filter((lambda x: x[0] == 'update'), entity.links))
implicit_id_required = splunk.util.normalizeBoolean(entity.get('update.implicit_id_required', None))
sbAppId = ''
if 'details' in entity and ('/' in entity['details']):
sbAppId = entity['details'][entity['details'].rfind('/')+1:]
if implicit_id_required:
update_link_text = _('Overwrite with')
else:
update_link_text = _('Update to')
endif
%>
% if isAppList and (element.get('elementName') == 'version') and update_link:
% if not (isCloud and not isDMCDisabled):
|
${_('%s %s' % (update_link_text, entity.get('update.version', None)))}
% endif
% endif
% endif
|
% endif
% endif
% endif
% endfor
%def>
% if len(entities) == 0:
<%
try:
hasCreateLink = list(filter((lambda x: x[0] == 'create'), entities.links))
except:
hasCreateLink = False
%>
<%
if endpoint_path=='authentication/users':
no_entities_msg = _('User "%s" was not found. Click the "New User" button to create a new user.') % kwargs.get("search")
else:
no_entities_msg = _('There are no configurations of this type. ') + (showNewButton and hasCreateLink and _('Click the "%s" button to create a new configuration.') % newLabel or "")
%>
| <%doc>TRANS: Displayed if no admin entities exist to list%doc>${no_entities_msg |h} |
% endif
<%
visibleApps = en.getEntities("apps/local", search=['visible=true'], count=-1)
%>
% for entity in entities.values():
<%
isDeletable = False if ((endpoint_path in ['data/inputs/win-wmi-collections'] and (entity.name in ['CPUTime', 'FreeDiskSpace', 'LocalNetwork', 'Memory', 'LocalProcesses', 'LocalPhysicalDisk'])) or (endpoint_path in ['data/inputs/win-event-log-collections'] and entity.name=='localhost') ) else True
_isClonable = isClonable and (endpoint_path not in ['authentication/users', 'data/inputs/tcp/cooked'] or ('type' in entity and entity['type'] == 'Splunk'))
entityDisplayName = entity[displayNameField] if displayNameField else entity.name
%>
% if "elements" in uiHelper:
<%
headerRow = False
if countRows == 0:
headerRow = True
isModifiable = True if entity['eai:acl']['modifiable']=="1" else False
isScheduled = True if entity.get('is_scheduled')=="1" else False
%>
% if headerRow:
<%call expr="genDataCells(uiHelper['elements'], endpoint_path, headerRow)"/>
% if showPermissionsColumn:
% if isModifiable:
<% countCols += 1 %>
|
<%call expr="makeSortHeading(_('Sharing'), 'eai:acl.sharing', kwargs)"/>
|
% endif
%endif
% if showEnabledColumn:
<% countCols += 1 %>
<%call expr="makeSortHeading(_('Status'), 'disabled', kwargs)"/>
|
% endif
% if showActionsColumn:
<% countCols += 1 %>
${_('Actions')} |
% endif
<%
## the header has been created, proceed...
headerRow = False
countCols = 0
countRows += 1
%>
% endif
<% entity_endpoint_path = entity.get('endpoint_base', endpoint_path) %>
<%call expr="genDataCells(uiHelper['elements'], entity_endpoint_path, headerRow)"/>
% if showPermissionsColumn:
% if isModifiable:
<% countCols += 1 %>
|
<% list_links = list(filter((lambda x: x[0] == 'list'), entity.links)) %>
${sharing_names.get(entity['eai:acl']['sharing'], "")}
% if list_links and (entity['eai:acl'].get('sharing', None) != 'user' or entity['eai:acl'].get('can_share_app', None) == '1'):
<% qs = dict(manager_cancel_url=util.strip_url(current_url_path(include_qs=True)), uri=list_links[0][1]) %>
| ${_("Permissions")}
% endif
|
% endif
%endif
% if showEnabledColumn:
<% countCols += 1 %>
% if isEnablable:
<%
if not splunk.util.normalizeBoolean(entity.get('disabled',None)):
enabledState = _("Enabled")
else:
enabledState = _("Disabled")
endif
%>
${enabledState}
% if entity['eai:acl']['can_write']=='1':
% for ctrl in ('disable', 'enable'):
<% ctrl_links = list(filter((lambda x: x[0] == ctrl), entity.links)) %>
% if ctrl_links:
<%
ctrlUrl = ctrl_links[0][1].replace("'","\\'")
ctrlEntity = entityDisplayName.replace("\\","\\\\").replace("'","\\'")
if endpoint_path.startswith('deployment/server/setup/data/inputs/'):
ctrlEntitySpecial = entityDisplayName ## deployment endpoint doesnt require extra backslash or apostrophe escaping
ctrlUrl = '/services/%s/%s/%s?app_name=%s' % (endpoint_path, urllib_parse.quote(ctrlEntitySpecial.encode('utf8')).replace('/','%2F'), ctrl, urllib_parse.quote(entity['eai:acl']['app'].encode('utf8')))
endif
%>
<% jscall = "doObjectAction('%s', '%s', '%s'); return false;" % ( ctrl.replace("'","\\'"), ctrlUrl, ctrlEntity ) %>
|
<% all_tags = _(' all tags for pair') if endpoint_path == 'saved/fvtags' else '' %>
${_(action_names[ctrl]) + all_tags}
<% needs_sep = True %>
% endif
% endfor
% endif
% endif
|
% endif
% if showActionsColumn:
<% countCols += 1 %>
<% needs_sep = False %>
% if (isSavedsearches and isScheduled):
% if needs_sep:
|
<% needs_sep = False %>
% endif
${_("View recent")}
<% needs_sep = True %>
% endif
% if (isSavedsearches):
% if needs_sep:
|
<% needs_sep = False %>
% endif
<% qs = {'s':entity.getLink("alternate")} %>
${_("Run")}
<% needs_sep = True %>
% endif
% if (isSavedsearches and showAdvancedEdit):
% if needs_sep:
|
<% needs_sep = False %>
% endif
% if qsdict:
<% qs = dict(s=list_links[0][1], ns=qsdict.get('ns',''), pwnr=qsdict.get('pwnr',''), count=qsdict.get('count',''), search=qsdict.get('search',''))%>
% else:
<% qs = {'s': list_links[0][1]} %>
% endif
${_("Advanced edit")}
<% needs_sep = True %>
% endif
% if isLDAP and ('disabled' not in entity or entity['disabled'] == '0'):
% if needs_sep:
|
<% needs_sep = False %>
% endif
<% qs = {'api.strategy':entity.name} %>
${_("Map groups")}
<% needs_sep = True %>
% endif
% if isViews and (entity['eai:acl']['app'] in visibleApps) and ('disabled' not in entity or entity['disabled'] == '0'):
% if needs_sep:
|
<% needs_sep = False %>
% endif
${_("Open")}
<% needs_sep = True %>
% endif
% if isDeploymentserverclass:
% if needs_sep:
|
<% needs_sep = False %>
% endif
<%
link_url = list(filter((lambda x: x[0] == "status"), entity.links))[0][1]
link_url_parts = link_url.split('/')
status_link = ""
if link_url_parts[1] == "servicesNS":
# for servicesNS, remove the app and user parts + deployment since that is where we are.
status_link = link_url_parts[5:]
else:
# for services, there are no app and user parts to remove
status_link = link_url_parts[2:]
%>
${_('Status')}
<% needs_sep = True %>
% endif
% if isDistributedSearchPeers:
<% quarantine_link = list(filter((lambda x: x[0] == 'quarantine'), entity.links)) %>
<% unquarantine_link = list(filter((lambda x: x[0] == 'unquarantine'), entity.links)) %>
% if quarantine_link:
% if needs_sep:
|
<% needs_sep = False %>
% endif
<% jscall = "doObjectAction('quarantine', %s, %s);" % ( jsonify(quarantine_link[0][1]), jsonify(entityDisplayName) ) %>
${_(action_names['quarantine'])}
<% needs_sep = True %>
% endif
% if unquarantine_link:
% if needs_sep:
|
<% needs_sep = False %>
% endif
<% jscall = "doObjectAction('unquarantine', %s, %s);" % ( jsonify(unquarantine_link[0][1]), jsonify(entityDisplayName) ) %>
${_(action_names['unquarantine'])}
<% needs_sep = True %>
% endif
% endif
% if isAppList:
<% hasSetup = False %>
% if needs_sep:
|
<% needs_sep = False %>
% endif
% if list(filter((lambda x: x[0] == 'setup'), entity.links)) or cached.isModSetup(entity.name):
<% qs = {'action':'edit'} %>
<%
hasSetup = True
if entity.name == "windows":
qs["redirect_override"]="/app/windows"
endif
%>
% if 'setup_view' in entity:
${_("Set up")}
% else:
${_("Set up")}
% endif
<% needs_sep = True %>
% endif
% if (entity['visible'] == '1') and (entity['disabled'] == '0') and not ((entity['configured'] == '0') and hasSetup):
% if needs_sep:
|
<% needs_sep = False %>
% endif
${_("Launch app")}
<% needs_sep = True %>
% endif
% if entity['disabled'] == '0':
% if needs_sep:
|
<% needs_sep = False %>
% endif
<% qs = {'action':'edit'} %>
${_("Edit properties")}
<% needs_sep = True %>
% endif
% if entity['disabled'] == '0':
% if needs_sep:
|
<% needs_sep = False %>
% endif
<% qs = {'ns':entity.name, 'app_only':'1'} %>
${_("View objects")}
<% needs_sep = True %>
% endif
% if 'details' in entity:
% if needs_sep:
|
<% needs_sep = False %>
% endif
${_("View details on Splunkbase")}
<% needs_sep = True %>
% endif
% else:
<% list_links = list(filter((lambda x: x[0] == 'list'), entity.links)) %>
% if _isClonable and list_links and hasCreateLink:
% if needs_sep:
|
<% needs_sep = False %>
% endif
<% needs_sep = True %>
<%doc>TRANS: Clicked to clone an existing enity%doc>${_('Clone')}
% endif
% if hasCreateLink and showAppContext:
<% move_link = list(filter((lambda x: x[0] == 'move'), entity.links)) %>
% if move_link:
% if needs_sep:
|
<% needs_sep = False %>
% endif
<% needs_sep = True %>
<%
if entity['eai:acl']['sharing']=='user':
owner = entity.owner
else:
owner = "nobody"
endif
jscall = "moveObjectToApp(%s,%s,%s); return false;" % (jsonify(move_link[0][1]), jsonify(entityDisplayName), jsonify(owner))
%>
<%doc>TRANS: Clicked to move an existing enity to a different namespace%doc>${_('Move')}
% endif
% endif
% if (isSavedsearches):
<% unembed_link = list(filter((lambda x: x[0] == 'unembed'), entity.links)) %>
% if (unembed_link):
% if needs_sep:
|
<% needs_sep = False %>
% endif
<% jscall = "doObjectAction('unembed', %s, %s);" % ( jsonify(unembed_link[0][1]), jsonify(entityDisplayName) ) %>
${_(action_names['unembed'])}
<% needs_sep = True %>
% endif
% endif
<% ctrl_links = list(filter((lambda x: x[0] == 'remove'), entity.links)) %>
% if isDeletable and ctrl_links:
% if needs_sep:
|
% endif
<%
ctrlUrl = ctrl_links[0][1].replace("'","\\'")
ctrlEntity = entityDisplayName.replace("\\","\\\\").replace("'","\\'")
if endpoint_path.startswith('deployment/server/setup/data/inputs/'):
ctrlEntitySpecial = entityDisplayName ## deployment endpoint doesnt require extra backslash or apostrophe escaping
ctrlUrl = '/services/%s/%s?app_name=%s' % (endpoint_path, urllib_parse.quote(ctrlEntitySpecial.encode('utf8')).replace('/','%2F'), urllib_parse.quote(entity['eai:acl']['app'].encode('utf8')))
endif
%>
<% jscall = "doObjectAction('remove', '%s', '%s'); return false;" % ( ctrlUrl, ctrlEntity ) %>
% if isRolesList:
% if needs_sep:
|
% endif
${_('View Capabilities')}
|
% endif
${_(action_names['remove'])}
% endif
% endif
|
% endif
<% countCols = 0 %>
% endif
<% countRows += 1 %>
% endfor
%def>
<%def name="menulist(namespace, menuDict)">
<%
label = menuDict.get("label", None)
menuItems = menuDict.get("menuItems",[]) # menu items is a list of dicts.
%>
% if label:
${_(label)}
% endif
% for item in menuItems:
<%
itemLabel = item.get("label", "A label is required for this item.")
itemUrl = item.get("url", None)
itemDescription = item.get("description", None)
links = item.get("links", None)
currentUser=auth.getCurrentUser()['name']
itemId=item.get("id", "default")
adminAccessibleOnly = ['forwarding', 'apps']
if isLite:
if itemId == 'server-controls':
continue
if itemId in adminAccessibleOnly and not isAdmin:
continue
if itemId == 'apps' and isCloud:
continue
if itemId == 'forwarding' and isCloud:
continue
%>
-
% if itemUrl:
${_(itemLabel)}
% else:
${_(itemLabel)}
% endif
% if links:
% for link in links:
<%
label = link.get("label", "label is required and not provided")
url = "#"
localUrl = link.get("local-url", None)
remoteUrl = link.get("remote-url", None)
if remoteUrl != None:
url = remoteUrl
target = "_blank"
## local url's win if both are defined
if localUrl != None:
url = make_url(localUrl % dict(namespace=cpQuoteEntity(namespace),currentUser=cpQuoteEntity(currentUser)))
target = "_top"
%>
|${_(label)}
% endfor
% endif
% if itemDescription:
- ${_(itemDescription)}
% endif
% endfor
%def>
## used by admin/EAI to hook events into widgets
<%def name="wireElementEvents(element, eltype=None)">
<%
eltype = eltype if eltype else element['type']
%>
% if 'onChange' in element and eltype in ('select', 'multiselect', 'hidden', 'text'):
onchange="${'Splunk.EAI.getInstance().doElementOnChange(this, %s)' % (jsonify(element['elementName']).replace('"', "'"))}"
% endif
% if 'onChange' in element and eltype in ('radio','checkbox','button') :
onclick="${'Splunk.EAI.getInstance().doElementOnChange(this, %s)' % (jsonify(element['elementName']).replace('"', "'"))}"
% endif
%def>
<%def name="header(namespace)">
%def>
<%def name="displayrestartbutton(displayRestartButton=True, return_to='')">
% if displayRestartButton:
<%doc>TRANS: Clicked to restart splunkd%doc>${_('Restart Splunk')}
% endif
%def>