BRGVersion:6
revision:$Revision$
UUID:b585f926-bc5e-4c09-8dc7-1490de92b7cb
timestamp:1510066041
baselib:core
baselib:lal1

begin:graphprops
propdef:GraphName|string|1||None
propdef:AutomationHost|string|1||None
propdef:AutomationPort|string|1||None
propdef:AutomationUsername|string|1||None
propdef:AutomationPassword|password|1||None
propdef:smtpServer|string|1||None
prop:GraphName=LM_List_Users
prop:AutomationHost=localhost
prop:AutomationPort={{%ls.brain.webapp.port%}}
prop:AutomationUsername=admin
encrypted:simple=nFZhmIpdcU/tLMZFEdRHethHrEDx+VB7RwHjepm0jxk=
prop:smtpServer=mailrelay.comcast.com
end:graphprops

libnode:SMTP_Mail
bretype:core::Python
editor:Label=SMTP Mail
editor:handle=56f1989f708b3a66
editor:sortkey=49ef3a00051d2f02_2
prop:AUTHREQUIRED=false
prop:ColumnOrder={{^^}}
prop:Enabled=true
prop:GroupBy={{^^}}
prop:Mandatory=false
prop:Python2Implementation=<<EOX
import braininfo
import smtplib
import datetime
import time
import string
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders
import os

def substituteMessageVars(self,rec):
	message = self.message
	#self.logInfo(self.message)
	for idx,field in enumerate(self.inputs[0].metadata):
		#self.logInfo(field[0] + '=' + str(rec[idx]))
		message = message.replace('//' + field[0] + '//',str(rec[idx]))
	#self.logInfo(self.message)
	return(message)
	
def sendmail(self):
	smtpServer = self.properties.getString('ls.brain.smtpmail.smtpServer')
	AUTHREQUIRED = self.properties.getBool('ls.brain.smtpmail.authRequired') # if you need to use SMTP AUTH set to 1
	smtpUser = self.properties.getString('ls.brain.smtpmail.smtpUser')  # for SMTP AUTH, set SMTP username here
	smtpPass = self.properties.getString('ls.brain.smtpmail.smtpPass')  # for SMTP AUTH, set SMTP password here
	SSLREQUIRED = self.properties.getBool('ls.brain.smtpmail.sslRequired')
	smtpPort = self.properties.getInt('ls.brain.smtpmail.smtpPort',25)

	Recipients = self.properties.getString('ls.brain.smtpmail.Recipients','')
	if self.Recipients2 != '':
		Recipients = Recipients + ',' + self.Recipients2
	Sender = self.properties.getString('ls.brain.smtpmail.Sender','LavastormBrainServer')
	Subject = self.properties.getString('ls.brain.smtpmail.Subject','Message from Brain')

	message = ""
	message = message + "<html>\r\n"
	message = message + "<body>\r\n"
	
	if self.bodymessage != '':
		message = message + self.bodymessage
	if self.bodytext != '':
		message = message + "\r\n\r\n"+ self.bodytext 

	message = message + "</body>\r\n"
	message = message + "<html>\r\n"

	msg = MIMEMultipart()
	msg['From'] = Sender 
	msg['To'] = Recipients
	msg['Subject'] = Subject 
	msg.attach(MIMEText(message,'html'))

	files=[]
	if self.properties.getString('ls.brain.smtpmail.filestoattach',"") <> '':
		t = self.properties.getString('ls.brain.smtpmail.filestoattach',"").split(",")
		files.extend(t)
	if self.attachFiles <> '':
		t = self.attachFiles.split(",")
		files.extend(t)
	#self.logInfo("C="+str(t))
	for file in files:
		bad=False
		try:
			f = open(file,"rb")
		except IOError:                     
			bad = True
		if not bad:
			part = MIMEBase('application', "octet-stream")
			part.set_payload( f.read() )
			Encoders.encode_base64(part)
			part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file))
			msg.attach(part)

	server = smtplib.SMTP(smtpServer, smtpPort)
	#server.set_debuglevel(1)
	server.ehlo()
	if SSLREQUIRED:
	    server.starttls()
	    server.ehlo()
	if AUTHREQUIRED:
	    server.login(smtpUser,smtpPass)
	if Recipients != '':
		server.sendmail('', Recipients.split(','), msg.as_string() )
	server.rset()
	server.quit()
	server.close()
	
def setemailheader(self):
	self.header = '<tr>'
	for idx,field in enumerate(self.columnOrder):
		self.header = self.header + '<td>' + field.strip()

def setemailrcp2(self,rec):
	if len(self.inputs) > 0 and self.rcp2f != '':
		self.Recipients2 = rec[self.rcp2f]
	else:
		self.Recipients2 = ''

def setemailbody(self):
	self.bodytext = '<table border=1 style="border-collapse:collapse">\n'
	if self.sendHeaders or true:
		self.bodytext = self.bodytext + self.header + '\n'
	
def closeandsendemail(self):
	if self.bodytext != '':
		self.bodytext = self.bodytext + '</table>\n'
	if self.bodytext != '' or self.sendZeroInput:
		sendmail(self)
		setemailbody(self)
	else:
		self.logInfo('Zero Input - email not sent')

def setup(brainNodeControlObj, BrainNodeClass):
	class BrainNode(BrainNodeClass):
		def initialize(self):
			super(BrainNode, self).initialize()
			self.sendZeroInput = self.properties.getBool('ls.brain.smtpmail.sendZeroInput')
			self.sendHeaders = self.properties.getBool('ls.brain.smtpmail.sendHeaders',True)
			self.columnOrder = self.properties.getString('ls.brain.smtpmail.columnOrder','').split(',')
			self.Recipients = self.properties.getString('ls.brain.smtpmail.Recipients','')
			self.rcp2f = self.properties.getString('ls.brain.smtpmail.RecipientsField','')
			self.attachFileNameField = self.properties.getString('ls.brain.smtpmail.attachFileNameField',"")
			#self.logInfo("A="+self.attachFileNameField)
			
			if self.Recipients=='' and self.rcp2f=='':
				raise Exception, 'No recipients specified'
				return False
			self.message = ''
			self.header = ''
			self.attachFiles=''
			fn = self.properties.getString('ls.brain.smtpmail.Message','')
			if fn != '':
				f=open(fn,"r")
				self.message = f.read()
			self.bodymessage=self.message
			self.reccount=0
			if len(self.inputs) > 0:
				setemailheader(self)
				rec = self.inputs[0].read()
				if rec:
					self.reccount=1
					if self.attachFileNameField <> "":
						self.attachFiles=rec[self.attachFileNameField]
			else:
				rec = ''
			setemailrcp2(self,rec)
			setemailbody(self)
			if len(self.inputs) > 0:
				gbv='_all_'
				gb = self.properties.getString('ls.brain.smtpmail.GroupBy','')
				if gb != '':
					gbv=rec[gb]
				if rec:
					self.bodymessage=substituteMessageVars(self,rec)
					setemailrcp2(self,rec)
				while rec:
					if self.attachFileNameField <> "":
						#self.logInfo("D1="+str(rec["FileName"]))
						#self.logInfo("D2="+str(self.attachFileNameField))
						self.attachFiles = str(rec[str(self.attachFileNameField)])
						#self.logInfo("D3="+str(self.attachFiles))
					self.bodytext = self.bodytext + '<tr>\n'
					for idx,field in enumerate(self.columnOrder):
						if field.strip() <> '':
							self.bodytext = self.bodytext+ '<td>' + str(rec[field.strip()]) + '\n'
					rec = self.inputs[0].read()
					self.reccount=self.reccount+1
					if gb <> '':
						if rec and rec[gb]<>gbv:
							closeandsendemail(self)
							self.bodymessage=substituteMessageVars(self,rec)
							setemailrcp2(self,rec)
							gbv=rec[gb]
							time.sleep(1)
			if len(self.inputs) > 0:
				if self.reccount > 0:
					closeandsendemail(self)
				else:
					self.logInfo("No records to send")
			else:
				closeandsendemail(self)

		def finalize(self, val):
			super(BrainNode, self).finalize(val)

		def pump(self, quant):
			while quant.permitsRunning(self):
				return False
			return True  
	return BrainNode
EOX
prop:PythonCodeOnServer=true
prop:RecipientsField={{^^}}
prop:SSLREQUIRED=false
prop:SendWithZeroInput=true
prop:Sender=none@domain.com
prop:Subject=Test Email
prop:ToolCode=<<EOX
MinInputs=0
MinOutputs=0
MaxInputs=1
MaxOutputs=0

method CustomDisplayLabel
{
	return "SMTP Mail"  
}

method CustomDescription
{
		str = "SMTP Mail"
		return str;
}

EOX
encrypted:simple=nFZhmIpvaU/yEcZCC4ZZS8pHqFjs7z4=
prop:smtpPort=25
prop:smtpServer=localhost
prop:smtpUser=ssmith
editor:XY=400,80
editor:propdef=Recipients|string|1|ls.brain.smtpmail.Recipients|None
editor:propdef=RecipientsField|string|1|ls.brain.smtpmail.RecipientsField|None
editor:propdef=Sender|string|1|ls.brain.smtpmail.Sender|None
editor:propdef=Subject|string|1|ls.brain.smtpmail.Subject|Not Blank
editor:propdef=FilesToAttach|string|1|ls.brain.smtpmail.filestoattach|None
editor:propdef=AttachFileNameField|string|1|ls.brain.smtpmail.attachFileNameField|None
editor:propdef=Message|inlinefile|1|ls.brain.smtpmail.Message|None
editor:propdef=SendWithZeroInput|boolean|1|ls.brain.smtpmail.sendZeroInput|None
editor:propdef=ColumnOrder|string|1|ls.brain.smtpmail.columnOrder|None
editor:propdef=GroupBy|string|1|ls.brain.smtpmail.groupBy|None
editor:propdef=SendHeaders|boolean|1|ls.brain.smtpmail.sendHeaders|None
editor:propdef=smtpServer|string|2|ls.brain.smtpmail.smtpServer|Not Blank
editor:propdef=AUTHREQUIRED|boolean|2|ls.brain.smtpmail.authRequired|Not Blank
editor:propdef=smtpUser|string|2|ls.brain.smtpmail.smtpUser|Not Blank
editor:propdef=smtpPass|password|2|ls.brain.smtpmail.smtpPass|None
editor:propdef=SSLREQUIRED|boolean|2|ls.brain.smtpmail.sslRequired|Not Blank
editor:propdef=smtpPort|string|2|ls.brain.smtpmail.smtpPort|Number
editor:propdef=ToolCode|inlinefile,nil|2||None
editor:propoverride=Enabled|1
editor:propoverride=Python2Implementation|2
editor:propdoc=Recipients=List of people to send the email to.  Separate multiple entries with COMMAS
editor:propdoc=RecipientsField=Column from first record of Input1 that contains list of addresses to receive emails.   Separate multiple entries with COMMAS
editor:propdoc=Sender=The "Reply To" address for the email
editor:propdoc=Subject=Enter a subject line for the email
editor:propdoc=Subject=
editor:propdoc=FilesToAttach=To attach files to the message, enter a comma-separated list of filenames (with full paths) here.
editor:propdoc=FilesToAttach=These file(s) will be attached to every outgoing email, regardless of the GroupBy parameter
editor:propdoc=FilesToAttach=If you also specify the AttachFileNameField parameter, both sets of files will be added to the email.
editor:propdoc=FilesToAttach=
editor:propdoc=FilesToAttach=TODO: if a file is listed twice.. it will be added to the email twice
editor:propdoc=AttachFileNameField=To attach files to the message, enter a input fieldname that contains comma-separated list of filenames (with full paths).
editor:propdoc=AttachFileNameField=If you also specify the FilesToAttach parameter, both sets of files will be added to the email.
editor:propdoc=AttachFileNameField=
editor:propdoc=AttachFileNameField=TODO: if a file is listed twice.. it will be added to the email twice
editor:propdoc=AttachFileNameField=TODO: uncertain what will happen here with the GroupBy parameter.. it may only send the file first or last file referrenced in a Group of records
editor:propdoc=Message=Enter the message Body text here.  HTML codes will be honored.
editor:propdoc=Message=Use //columnname// for substitution of values from the first record of Input1
editor:propdoc=SendWithZeroInput=Select TRUE to send even if the input stream has zero records
editor:propdoc=ColumnOrder=Only columns listed here will be used. 
editor:propdoc=ColumnOrder=Columns from the input will be placed in the Body text in this order.   
editor:propdoc=ColumnOrder=If this list is empty, then all columns will be sent.
editor:propdoc=GroupBy=For each new value of this field found, a separate email will be transmitted
editor:propdoc=GroupBy=Note: if the records are not sorted by this value, multiple emails may result
editor:propdoc=GroupBy=
editor:propdoc=GroupBy=TODO: this only works with a single input field.
editor:propdoc=smtpServer=Name of the smtp server that will send the email.. in unix with SMTP enabled, use "localhost"
editor:propdoc=AUTHREQUIRED=If you need to use SMTP AUTH set to True
editor:propdoc=AUTHREQUIRED=
editor:propdoc=smtpUser=for SMTP AUTH, set SMTP username here
editor:propdoc=smtpPass=for SMTP AUTH, set SMTP password here
editor:propdoc=SSLREQUIRED=if you need to use SSL set to TRUE
editor:propdoc=smtpPort=default = 25
editor:propdoc=smtpPort=ssl = 425
editor:propdoc=smtpPort=ssl = 587
editor:propdoc=smtpPort=
end:SMTP_Mail

libnode:Send_Excel_File_2
bretype:core::Composite
editor:Label=Send Excel File
editor:handle=56f19b9f152930c5
editor:sortkey=5332e6224cc37e46_2
input:5332e62238b73de7/=
inputxy:0=60,130
inputrotation:0=0
inclockxy:Inclock=20,30
outclocklink:/=Remove_Attached_file
outclockxy:Outclock=530,40
prop:DefaultAction=Edit
prop:DeleteExcel=true
prop:ExcelFileName={{%p_ls_tempDir%}}/{{%graph.username%}}/{{%graph.graphname%}}/{{%graph.runname%}}/excel_file.xls
prop:FileToAttach={{^ExcelFileName^}}
prop:Message=<<EOX
List of LAE users.
These results were produced by the graph {{^GraphName^}}

EOX
prop:Sender={{%graph.username%}}
editor:XY=320,80
editor:propdef=GraphName|string|1||None
editor:propdef=Recipients|choice|1|
editor:propdef=Sender|string|1||None
editor:propdef=Subject|string|1||None
editor:propdef=ExcelFileName|string|1||None
editor:propdef=FileToAttach|string|1||None
editor:propdef=DeleteExcel|boolean|1||None
editor:propdef=Message|inlinefile|1||None
node:Output_Excel
bretype:core::Output Excel
editor:handle=56f19b9f506b7276
editor:sortkey=52656df713a84354_2
input:@49e34a5e55c82040/=^.5332e62238b73de7
inclock:/=*
inclock:/=Agg
prop:File={{^ExcelFileName^}}
prop:FormatOutput=true
prop:HeaderBold=true
editor:XY=170,130
end:Output_Excel

node:node
bretype:::SMTP Mail
editor:handle=56f19b9f400c5817
editor:sortkey=5265951b70176c81_2
inclock:/=Output_Excel
inclock:/=Filter
prop:FilesToAttach={{^FileToAttach^}}
prop:Subject={{^Subject^}}
prop:smtpServer={{^smtpServer^}}
editor:XY=360,130
end:node

node:Remove_Attached_file
bretype:core::Python
editor:Label=Remove Attached file
editor:handle=56f19b9f79c052db
editor:sortkey=5332e6160c7856b0
inclock:/=node
prop:Enabled="{{^FileToAttach^}}" != ""
prop:Python2Implementation=<<EOX
import braininfo
import os

def setup(brainNodeControlObj, BrainNodeClass):
	''' Must return a class that inherits from BrainNodeClass. '''	
	class BrainNode(BrainNodeClass):
		def initialize(self):
			''' Called at node initialization, before first pump.'''
			super(BrainNode, self).initialize()
			os.system("rm {{^FileToAttach^}} >/dev/null")

		def finalize(self, val):
			''' Called at node end, after last pump call. '''
			super(BrainNode, self).finalize(val)

		def pump(self, quant):
			while quant.permitsRunning(self):
				return False

	return BrainNode
EOX
editor:XY=450,130
editor:propdef=DelayBetweenCommands|string|1||None
editor:propdef=LogFile|string|1|ls.brain.node.ExecuteShellCommand.LogFile|None
end:Remove_Attached_file

node:Filter
bretype:core::Filter
editor:handle=56f19b9f5af25f63
editor:sortkey=53ab0411508c058c
input:@40fd2c74167f1ca2/=Static_Data.40fe6c55598828e5
output:@40fd2c7420761db6/=
prop:Script=<<EOX

emit *
#if "{{^FileToAttach^}}" <> "" and "{{^DeleteExcel^}}"== "true" then abort("Delete is turned ON, so FileToAttach should be {"+"{^^}}")
if "{{^FileToAttach^}}" == "" and "{{^Message^}}".strFindI("{{^ExcelFileName^}}") == -1 then abort("ExcelFileName missing from Message")

EOX
editor:XY=310,220
end:Filter

node:Static_Data
bretype:core::Static Data
editor:handle=56f19b9f37210f25
editor:sortkey=53ab04183630752d
output:@40fe6c55598828e5/=
inclock:/=Output_Excel
prop:StaticData=<<EOX
Clock
True
EOX
editor:XY=220,220
end:Static_Data

end:Send_Excel_File_2

libnode:Login_2
bretype:core::Composite
editor:Label=Login
editor:handle=56f2ce0879370b87
editor:sortkey=53908ee23701383f
editor:icon=serverCon.ico
output:539094bb6cd04d3d/=
outlink:0=/=Set_Token_Field_Name.40fd2c7420761db6
outputxy:0=430,140
outputrotation:0=0
inclockxy:Inclock=20,30
outclockxy:Outclock=400,30
prop:ContentTypeOutputField=LOGIN_CONTENT_TYPE
prop:DefaultAction=Edit
prop:HeaderOutputField=LOGIN_HEADER
prop:StatusCodeOutputField=LOGIN_STATUS
prop:StatusMessageOutputField=LOGIN_STATUS_MESSAGE
prop:TokenOutputField=LOGIN_TOKEN
editor:XY=140,80
editor:propdef=AutomationHost|string|Connect||None
editor:propdef=AutomationPort|string|Connect||None
editor:propdef=AutomationUsername|string|Connect||None
editor:propdef=AutomationPassword|password|Connect||None
editor:propdef=TokenOutputField|string|Output||None
editor:propdef=StatusCodeOutputField|string|Output||None
editor:propdef=HeaderOutputField|string|Output||None
editor:propdef=ContentTypeOutputField|string|Output||None
editor:propdef=StatusMessageOutputField|string|Output||None
node:Login
bretype:lal1::HTTP
editor:Label=Login
editor:handle=56f2ce085b7d6eda
editor:sortkey=538fa11d073a3f1f
output:@506b1e775ec369f0/=
prop:Body=<<EOX
{"username":"{{^AutomationUsername^}}","password":"{{^AutomationPassword^}}"}
EOX
prop:BodyParamType=Literal
prop:DataOutputField=LOGIN_RESPONSE
prop:DataOutputMode=Field
prop:Method=POST
prop:MethodParamType=Literal
prop:Url=http://{{^AutomationHost^}}:{{^AutomationPort^}}/login/rest
prop:UrlParamType=Literal
editor:XY=120,150
end:Login

node:JSON_Data
bretype:lal1::JSON Data
editor:handle=56f2ce082332124e
editor:sortkey=538fa67c3a322f26
input:538fa69d7270040b/response=Login.506b1e775ec369f0
output:@51781d234c465db7/=
output:@522743291aa237ba/=
output:@522743281dab2bc6/=
inclock:/=Throw_Error_on_Failure_2
prop:JsonData=LOGIN_RESPONSE
prop:JsonDataParamType=Data Field
editor:XY=230,150
end:JSON_Data

node:Set_Token_Field_Name
bretype:core::Filter
editor:Label=Set Token Field Name
editor:handle=56f2ce085a415580
editor:sortkey=539090de31d82a05
input:@40fd2c74167f1ca2/=JSON_Data.51781d234c465db7
output:@40fd2c7420761db6/=
prop:Script=<<EOX

emit *
rename 'message' as "{{^TokenOutputField^}}"
exclude 'code'
EOX
editor:XY=330,140
end:Set_Token_Field_Name

node:Throw_Error_on_Failure_2
bretype:core::Filter
editor:Label=Throw Error on Failure
editor:handle=56f2ce0871ab1de5
editor:sortkey=55cd4008076c332b_2
input:@40fd2c74167f1ca2/=Login.506b1e775ec369f0
output:@40fd2c7420761db6/=
prop:Script=<<EOX
emit *
if execCount > 0 and LOGIN_STATUS <> 200
then abort(str(LOGIN_STATUS_MESSAGE))
EOX
editor:XY=180,230
end:Throw_Error_on_Failure_2

end:Login_2

libnode:LAE_Properties
bretype:core::Python
editor:Label=LAE Properties
editor:handle=5577ce5a63070365
editor:sortkey=551b46202ca15360
output:4649fd1f3e8079a3/=
prop:Python2Implementation=<<EOX
import braininfo
import os

def setup(brainNodeControlObj, BrainNodeClass):
	class BrainNode(BrainNodeClass):
		def initialize(self):
			super(BrainNode, self).initialize()
			self.om = self.newMetadata()
			self.om.append("Zone","string")
			self.om.append("Property","string")
			self.om.append("Type","string")
			self.om.append("Value","string")
			self.outputs[0].metadata = self.om
			for v in self.properties.getPropertyNames():
				outRec = self.outputs[0].newRecord()
				outRec["Zone"] = "Brain"
				outRec["Property"] = v
				if self.properties.isArray(v) == True:
					outRec["Type"] = "Array"
					a = self.properties.getArray(v)
					for vv in a[0:]:
						if not vv:
							w=''
						else:
							w=str(vv)
						outRec["Value"] =  w
						self.outputs[0].write(outRec)
				else:
					outRec["Value"] = self.properties.getString(v)
					outRec["Type"] = "String"
					self.outputs[0].write(outRec)
			for v in os.environ.keys():
				outRec = self.outputs[0].newRecord()
				outRec["Zone"] = "OS"
				outRec["Property"] = v
				outRec["Type"] = "String"
				outRec["Value"] = os.environ[v]
				self.outputs[0].write(outRec)


		def finalize(self, val):
			super(BrainNode, self).finalize(val)

		def pump(self, quant):
			while quant.permitsRunning(self):
				# your code here

				# when complete				
				return False
			# finished your quantum, you want pump called again
			return True  

	return BrainNode
EOX
prop:PythonCodeOnServer=true
editor:XY=70,80
end:LAE_Properties

libnode:LM_API_Query
bretype:core::Composite
editor:Label=LM_API_Query
editor:handle=56f2ca265fb819b9
editor:sortkey=56f2ca265fb819b9
input:56f2ca2731671ab8/=
inputxy:0=200,90
inputrotation:0=0
output:56f2ca2709644a74/=
outlink:0=/=JSON_Data_4.51781d234c465db7
outputxy:0=580,80
outputrotation:0=0
prop:DefaultAction=Edit
prop:Method=GET
prop:Query=<<EOX
apiCall = "/api/1/users"
EOX
prop:URL_Builder=<<EOX
{{^Query^}}
queryUrl = "http://{{^AutomationHost^}}:{{^AutomationPort^}}"
queryUrl = queryUrl + apiCall
if apiCall.strFind("?")== -1 
then queryUrl=queryUrl+"?"
else queryUrl=queryUrl+"&" 

queryUrl = queryUrl + "ltk=" + 'LOGIN_TOKEN' 

emit LOGIN_TOKEN
emit queryUrl as QUERY_URL
EOX
editor:XY=220,80
editor:propdef=Method|choice|1||GET|PUT
editor:propdef=Query|text|1||None
editor:propdef=URL_Builder|text|1||None
editor:propdef=Body_Script|text|1||None
node:JSON_Data_4
bretype:lal1::JSON Data
editor:handle=56198abc0ba83ec2
editor:sortkey=56198abc0ba83ec2
input:56198abe70e45517/response=HTTP.506b1e775ec369f0
output:@51781d234c465db7/Data=
output:@522743291aa237ba/=
output:@522743281dab2bc6/=
prop:CharacterDataOutputFieldType=String
prop:JsonData=RESPONSE
prop:JsonDataParamType=Data Field
prop:RemoveCommonPrefixes=true
editor:XY=470,90
end:JSON_Data_4

node:HTTP
bretype:lal1::HTTP
editor:handle=5625939c1eba4b94
editor:sortkey=5625939c1eba4b94
input:53a4766d580a597e/out1=Build_QueryUrl.40fd2c7420761db6
output:@506b1e775ec369f0/=
prop:ContentType=text/plain
prop:ContentTypeOutputField=CONTENT_TYPE
prop:ContentTypeParamType=Literal
prop:DataOutputField=RESPONSE
prop:DataOutputFieldEncoding=None
prop:DataOutputFieldType=Unicode
prop:MethodParamType=Literal
prop:PassThroughFields=Unused
prop:StatusCodeOutputField=STATUS_CODE
prop:StatusMessageOutputField=STATUS_MESSAGE
prop:Url=QUERY_URL
prop:UrlParamType=Field
editor:XY=380,90
end:HTTP

node:Build_QueryUrl
bretype:core::Filter
editor:Label=Build QueryUrl
editor:handle=5625939c433e0678
editor:sortkey=5625939c433e0678
input:@40fd2c74167f1ca2/=^.56f2ca2731671ab8
output:@40fd2c7420761db6/=
prop:Script=<<EOX
{{^URL_Builder^}}
EOX
editor:XY=290,90
end:Build_QueryUrl

end:LM_API_Query

libbox:
label:Publishing
rect:260,30,260,100
backgroundcolor:13434879
end:
libbox:
label:Logistics
rect:30,30,220,100
backgroundcolor:13434879
end:
node:Login
bretype:::Login
editor:handle=5625939c53b1164c
editor:sortkey=5625939c53b1164c
output:@539094bb6cd04d3d/=
inclockxy:Inclock=20,30
outclockxy:Outclock=400,30
editor:XY=100,80
node:
bretype:::Login
editor:handle=5625939c31f736ed
editor:shadow=56f2ce085b7d6eda
output:@506b1e775ec369f0/=
end:

node:
bretype:::JSON Data
editor:handle=5625939c58d876a1
editor:shadow=56f2ce082332124e
input:@538fa69d7270040b/=
output:@51781d234c465db7/=
output:@522743291aa237ba/=
output:@522743281dab2bc6/=
end:

node:
bretype:::Set Token Field Name
editor:handle=5625939c10d82ceb
editor:shadow=56f2ce085a415580
input:@40fd2c74167f1ca2/=
output:@40fd2c7420761db6/=
end:

node:
bretype:::Throw Error on Failure
editor:handle=5625939c083a58a7
editor:shadow=56f2ce0871ab1de5
input:@40fd2c74167f1ca2/=
output:@40fd2c7420761db6/=
end:

end:Login

node:Drop_Fields
bretype:core::Filter
editor:Label=Drop Fields
editor:handle=5625b42154016012
editor:sortkey=5625b42154016012
input:@40fd2c74167f1ca2/=Login.539094bb6cd04d3d
output:@40fd2c7420761db6/=
prop:Script=<<EOX
emit LOGIN_TOKEN
EOX
editor:XY=190,80
end:Drop_Fields

node:Drop_Columns
bretype:core::Filter
editor:Label=Drop Columns
editor:handle=56f1976558107ccd
editor:sortkey=56f1976558107ccd
input:@40fd2c74167f1ca2/=Users.56f2ca2709644a74
output:@40fd2c7420761db6/=
prop:Script=<<EOX
emit name
emit active
emit imported
emit createdBy
emit createdOn
emit ID
t=find(inputFields(1),"principalImportDetails.uniqueImportReference") 
if t>-1 then LDAP_id=str(field("1:"+str(t+1))) else LDAP_id=str(null)
emit LDAP_id

EOX
editor:XY=480,80
end:Drop_Columns

node:Sort
bretype:core::Sort
editor:handle=56f197fd4f37728d
editor:sortkey=56f197fd4f37728d
input:@40fd2c743ebf4304/=Lookup_2.40fd2c7445835585
output:@40fd2c746a2a3b47/=
prop:CompareOrderExpr=<<EOX
name
EOX
editor:XY=1000,80
end:Sort

node:Agg_Ex
bretype:core::Agg Ex
editor:handle=56f1d37478b3150b
editor:sortkey=56f1d0bd53ab4df0
input:@4b4668c040aa5a85/=Sort_4.40fd2c746a2a3b47
output:@4b4668e708143fb4/=
prop:GroupBy=<<EOX
UserName
EOX
prop:Script=<<EOX
emit referencedFields(1,{{^GroupBy^}})
r=groupString(Role,",")
emit r as Roles
where lastInGroup

EOX
prop:SortInput=false
editor:XY=750,170
node:
bretype:::Bypass
editor:handle=56f1d37462797d01
editor:shadow=4b467f7e02db3a85
input:@4b467f7e129d45c1/=
input:@4b467f830ffe047b/=
output:@40fd2c7436717256/=
end:

node:
bretype:::Sort
editor:handle=56f1d37426647af8
editor:shadow=4b467f8972dc33df
input:@40fd2c743ebf4304/=
output:@40fd2c746a2a3b47/=
end:

node:
bretype:::Agg
editor:handle=56f1d37417f30a14
editor:shadow=4b467f9b3d5028c0
input:@40fd2c7427456e5b/=
output:@40fd2c744c862db0/=
end:

end:Agg_Ex

node:Agg_Ex_2
bretype:core::Agg Ex
editor:handle=56f2b66405777631
editor:sortkey=56f1d0bd53ab4df0_2
input:@4b4668c040aa5a85/=Sort_3.40fd2c746a2a3b47
output:@4b4668e708143fb4/=
prop:GroupBy=<<EOX
UserName
EOX
prop:Script=<<EOX
emit referencedFields(1,{{^GroupBy^}})
r=groupString(Role,",")
emit r as Group_Roles
g=groupString(Group,",")
emit g as Groups
where lastInGroup

EOX
prop:SortInput=false
editor:XY=750,250
node:
bretype:::Bypass
editor:handle=56f2b664223527c0
editor:shadow=4b467f7e02db3a85
input:@4b467f7e129d45c1/=
input:@4b467f830ffe047b/=
output:@40fd2c7436717256/=
end:

node:
bretype:::Sort
editor:handle=56f2b6642dcd7d4b
editor:shadow=4b467f8972dc33df
input:@40fd2c743ebf4304/=
output:@40fd2c746a2a3b47/=
end:

node:
bretype:::Agg
editor:handle=56f2b66438ce5b83
editor:shadow=4b467f9b3d5028c0
input:@40fd2c7427456e5b/=
output:@40fd2c744c862db0/=
end:

end:Agg_Ex_2

node:Lookup_2
bretype:core::Lookup
editor:handle=56f1d374320d5cdf
editor:sortkey=56f1d2f30cac1b4a
input:@40fd2c746abc6dc7/=Drop_Columns.40fd2c7420761db6
input:@40fd2c74486e4494/=Lookup.40fd2c7445835585
output:@40fd2c7445835585/=
prop:InputKey=<<EOX
name
EOX
prop:LookupKey=<<EOX
UserName
EOX
prop:Script=<<EOX
emit 1:*
default emit 2:*
exclude 2:UserName
EOX
editor:XY=900,80
end:Lookup_2

node:BRD_Examiner
bretype:core::Filter
editor:Label=members.type = user
editor:handle=56f2a64b60dc7f1b
editor:sortkey=56f2a64b60dc7f1b
input:@40fd2c74167f1ca2/=Role_Members.56f2ca2709644a74
output:@40fd2c7420761db6/=
output:56f2a66b35a9644d/out2=
prop:Script=<<EOX
output 1 {
emit 'members.type' as Type 
emit 'members.name' as UserName
emit name as Role
where 'members.type' == "user"
}
output 2 {
emit 'members.type' as Type 
emit 'members.name' as Group
emit name as Role
where 'members.type' == "group"
}
EOX
editor:XY=480,170
end:BRD_Examiner

node:memberstype__user
bretype:core::Filter
editor:Label=members.type = user
editor:handle=56f2b1ed31fb2e09
editor:sortkey=56f2a64b60dc7f1b_2
input:@40fd2c74167f1ca2/=Group_Members.56f2ca2709644a74
output:@40fd2c7420761db6/=
prop:Script=<<EOX
output 1 {
emit 'members.type' as Type 
emit 'members.name' as UserName
emit name as Group
where 'members.type' == "user"
}

EOX
editor:XY=480,260
end:memberstype__user

node:Split_between_Users_and_Groups
bretype:core::X-Ref
editor:Label=Split between Users and Groups
editor:handle=56f2ad4b5524633d
editor:sortkey=56f2ad4b5524633d
input:@45781ca80c2802d0/=BRD_Examiner.56f2a66b35a9644d
input:@45781ca971fe502f/=memberstype__user.40fd2c7420761db6
output:@45781cad02e051b0/=
output:@457826825d7c2de0/=
output:@4578268450ad5d88/=
prop:LeftInputKey=<<EOX
Group
EOX
prop:RightInputKey=<<EOX
Group
EOX
prop:Script=<<EOX
output 1 {
    emit 1:*
    where join.leftOrphan
}

output 2 {
    emit 1:*
    emit 2:UserName
    exclude referencedFields(2,{{^RightInputKey^}})
    where join.match
}

output 3 {
    emit 2:*
    where join.rightOrphan
}
EOX
prop:SortLeftInput=true
prop:SortRightInput=true
editor:XY=560,250
node:
bretype:::Sort
editor:handle=56f2ad4b2155481a
editor:shadow=45782670131b71e8
input:@40fd2c743ebf4304/=
output:@40fd2c746a2a3b47/=
end:

node:
bretype:::Bypass
editor:handle=56f2ad4b22131502
editor:shadow=4578267017753cec
input:@45782010749f0c96/=
input:@457820124fef7658/=
output:@40fd2c7436717256/=
end:

node:
bretype:::Join
editor:handle=56f2ad4b36952bea
editor:shadow=457826701862249e
input:@40fd2c745b6d7704/=
input:@40fd2c74504921cd/=
output:@40fd2c7430f76546/=
output:@457826cc03a465f4/=
output:@457826cc510c69e0/=
end:

node:
bretype:::Bypass
editor:handle=56f2ad4b22304f40
editor:shadow=4578267041681261
input:@45782010749f0c96/=
input:@457820124fef7658/=
output:@40fd2c7436717256/=
end:

node:
bretype:::Sort
editor:handle=56f2ad4b205c4c53
editor:shadow=4578267075a60d09
input:@40fd2c743ebf4304/=
output:@40fd2c746a2a3b47/=
end:

end:Split_between_Users_and_Groups

node:Sort_4
bretype:core::Sort
editor:handle=56f2b62b12986183
editor:sortkey=56f2b62b12986183
input:@40fd2c743ebf4304/=BRD_Examiner.40fd2c7420761db6
output:@40fd2c746a2a3b47/=
prop:CompareOrderExpr=<<EOX
UserName,Role
EOX
editor:XY=660,170
end:Sort_4

node:Sort_3
bretype:core::Sort
editor:handle=56f2b66c3a1736f2
editor:sortkey=56f2b62b12986183_2
input:@40fd2c743ebf4304/=Split_between_Users_and_Groups.457826825d7c2de0
output:@40fd2c746a2a3b47/=
prop:CompareOrderExpr=<<EOX
UserName,Role,Group
EOX
editor:XY=660,250
end:Sort_3

node:Lookup
bretype:core::Lookup
editor:handle=56f2b6bc4b714f5c
editor:sortkey=56f2b6bc4b714f5c
input:@40fd2c746abc6dc7/=Agg_Ex.4b4668e708143fb4
input:@40fd2c74486e4494/=Agg_Ex_2.4b4668e708143fb4
editor:bend=1=810|250
output:@40fd2c7445835585/=
prop:InputKey=<<EOX
UserName
EOX
prop:LookupKey=<<EOX
UserName
EOX
prop:Script=<<EOX
emit 1:*
emit Groups,Group_Roles
EOX
editor:XY=840,170
end:Lookup

node:Users
bretype:::LM_API_Query
editor:Label=Users
editor:handle=56f2d2bf65654998
editor:sortkey=56f2d2bf65654998
input:@56f2ca2731671ab8/=Drop_Fields.40fd2c7420761db6
output:@56f2ca2709644a74/=
inclockxy:Inclock=20,30
outclockxy:Outclock=400,30
editor:XY=280,80
node:
bretype:::JSON Data
editor:handle=56f2d2bf4826683c
editor:shadow=56198abc0ba83ec2
input:@56198abe70e45517/=
output:@51781d234c465db7/=
output:@522743291aa237ba/=
output:@522743281dab2bc6/=
end:

node:
bretype:::HTTP
editor:handle=56f2d2bf1d2c4576
editor:shadow=5625939c1eba4b94
input:@53a4766d580a597e/=
output:@506b1e775ec369f0/=
prop:BodyParamType=Field
end:

node:
bretype:::Build QueryUrl
editor:handle=56f2d550447a539d
editor:shadow=5625939c433e0678
input:@40fd2c74167f1ca2/=
output:@40fd2c7420761db6/=
end:

end:Users

node:Roles_3
bretype:::LM_API_Query
editor:Label=Roles
editor:handle=56f2d2cf47c52d2f
editor:sortkey=56f2d2bf65654998_2
input:@56f2ca2731671ab8/=Drop_Fields.40fd2c7420761db6
editor:bend=0=220|170
output:@56f2ca2709644a74/=
prop:Query=<<EOX
apiCall = "/api/1/roles"
EOX
editor:XY=280,170
node:
bretype:::JSON Data
editor:handle=56f2d2cf01bb00ec
editor:shadow=56198abc0ba83ec2
input:@56198abe70e45517/=
output:@51781d234c465db7/=
output:@522743291aa237ba/=
output:@522743281dab2bc6/=
end:

node:
bretype:::HTTP
editor:handle=56f2d2cf2b4b1908
editor:shadow=5625939c1eba4b94
input:@53a4766d580a597e/=
output:@506b1e775ec369f0/=
end:

node:
bretype:::Build QueryUrl
editor:handle=56f2d2cf1b2f3cd5
editor:shadow=5625939c433e0678
input:@40fd2c74167f1ca2/=
output:@40fd2c7420761db6/=
end:

end:Roles_3

node:Groups
bretype:::LM_API_Query
editor:Label=Groups
editor:handle=56f2d304010714b7
editor:sortkey=56f2d2bf65654998_3
input:@56f2ca2731671ab8/=Drop_Fields.40fd2c7420761db6
editor:bend=0=220|260
output:@56f2ca2709644a74/=
prop:Query=<<EOX
apiCall = "/api/1/groups"
EOX
editor:XY=280,260
node:
bretype:::JSON Data
editor:handle=56f2d30465c2077b
editor:shadow=56198abc0ba83ec2
input:@56198abe70e45517/=
output:@51781d234c465db7/=
output:@522743291aa237ba/=
output:@522743281dab2bc6/=
end:

node:
bretype:::HTTP
editor:handle=56f2d30478332718
editor:shadow=5625939c1eba4b94
input:@53a4766d580a597e/=
output:@506b1e775ec369f0/=
end:

node:
bretype:::Build QueryUrl
editor:handle=56f2d3044f3150bd
editor:shadow=5625939c433e0678
input:@40fd2c74167f1ca2/=
output:@40fd2c7420761db6/=
end:

end:Groups

node:Role_Members
bretype:::LM_API_Query
editor:Label=Role Members
editor:handle=56f2d34c56030221
editor:sortkey=56f2d2bf65654998_4
input:@56f2ca2731671ab8/=Roles_3.56f2ca2709644a74
output:@56f2ca2709644a74/=
prop:Query=<<EOX
apiCall = "/api/1/roles/"+str('id')
EOX
editor:XY=380,170
node:
bretype:::JSON Data
editor:handle=56f2d34c7ce63667
editor:shadow=56198abc0ba83ec2
input:@56198abe70e45517/=
output:@51781d234c465db7/=
output:@522743291aa237ba/=
output:@522743281dab2bc6/=
end:

node:
bretype:::HTTP
editor:handle=56f2d34c56e66f18
editor:shadow=5625939c1eba4b94
input:@53a4766d580a597e/=
output:@506b1e775ec369f0/=
end:

node:
bretype:::Build QueryUrl
editor:handle=56f2d34c57657204
editor:shadow=5625939c433e0678
input:@40fd2c74167f1ca2/=
output:@40fd2c7420761db6/=
end:

end:Role_Members

node:Group_Members
bretype:::LM_API_Query
editor:Label=Group Members
editor:handle=56f2d3a7725a6317
editor:sortkey=56f2d2bf65654998_6
input:@56f2ca2731671ab8/=Groups.56f2ca2709644a74
output:@56f2ca2709644a74/=
prop:Query=<<EOX
apiCall = "/api/1/groups/"+str('id')
EOX
editor:XY=380,260
node:
bretype:::JSON Data
editor:handle=56f2d3a7711569a6
editor:shadow=56198abc0ba83ec2
input:@56198abe70e45517/=
output:@51781d234c465db7/=
output:@522743291aa237ba/=
output:@522743281dab2bc6/=
end:

node:
bretype:::HTTP
editor:handle=56f2d3a70ec34fad
editor:shadow=5625939c1eba4b94
input:@53a4766d580a597e/=
output:@506b1e775ec369f0/=
end:

node:
bretype:::Build QueryUrl
editor:handle=56f2d3a7261a1982
editor:shadow=5625939c433e0678
input:@40fd2c74167f1ca2/=
output:@40fd2c7420761db6/=
end:

end:Group_Members

node:Output_Excel
bretype:core::Output Excel
editor:handle=5a01c75e527d72e9
editor:sortkey=5a01c75e527d72e9
input:@49e34a5e55c82040/=Sort.40fd2c746a2a3b47
prop:File=/pathtomyfiles/LAE_Users.xlsx
editor:XY=1100,80
end:Output_Excel

