Update:
This is an older version of the question/script. The new version can be found here: Part 2: Create or update record via HTTP request
I have an external system that sends an HTTP request to a Jython script (in IBM's Maximo Asset Management platform).
The Jython 2.7.0 script does this:
- Accepts an HTTP request:
http://server:port/maximo/oslc/script/CREATEWO?_lid=wilson&_lpwd=wilson&f_wonum=LWO0382&f_description=LEGACY WO&f_classstructureid=1666&f_status=APPR&f_wopriority=1&f_assetnum=LA1234&f_worktype=CM
- Loops through parameters:
- Searches for parameters that are prefixed with
f_
('f' is for field-value) - Puts the parameters in a list
- Removes the prefix from the list values (so that the parameter names match the database field names).
- Searches for parameters that are prefixed with
- Updates or creates records via the parameters in the list:
- If there is an existing record in the system with the same work order number, then the script updates the exiting record with the parameter values from the list.
- If there isn't an existing record, then a new record is created (again, from the parameter values from the list).
- Finishes by returning a message to the external system (message: updated, created, or other (aka an error)).
Can the script be improved?
from psdi.mbo import SqlFormat
from psdi.server import MXServer
from psdi.mbo import MboSet
params = list( param for param in request.getQueryParams() if param.startswith('f_') )
paramdict={}
resp=''
for p in params:
paramdict[p[2:]]=request.getQueryParam(p)
woset = MXServer.getMXServer().getMboSet("workorder",request.getUserInfo())
#Prevents SQL injection
sqf = SqlFormat("wonum=:1")
sqf.setObject(1,"WORKORDER","WONUM",request.getQueryParam("f_wonum"))
woset.setWhere(sqf.format())
woset.reset()
woMbo = woset.moveFirst()
if woMbo is not None:
for k,v in paramdict.items():
woMbo.setValue(k,v,2L)
resp = 'Updated workorder ' + request.getQueryParam("f_wonum")
woset.save()
woset.clear()
woset.close()
else:
woMbo=woset.add()
for k,v in paramdict.items():
woMbo.setValue(k,v,2L)
resp = 'Created workorder ' + request.getQueryParam("f_wonum")
woset.save()
woset.clear()
woset.close()
responseBody = resp
Note 1: Previously, there was an SQL injection vulnerability in the code. This issue has been resolved via the SQLFormat java class. The code has been updated.
Note 2: Unfortunately, I'm not able to import Python 2.7.0 libraries into my Jython implementation. In fact, I don't even have access to all of the standard python libraries.
Note 3: The acronym 'MBO' stands for 'Master Business Object' (it's an IBM thing). For the purpose of this question, a Master Business Object can be thought of as a work order record. Additionally, the constant 2L tells the system to override any MBO rules/constraints.
f_wonum
isNumeric()
will prevent the SQL attacks for this script, assuming thatf_wonum
is a number. \$\endgroup\$f_wonum
is not a number. What I've done is utilized the SQLFormat Java class for this. I've updated Note 1 in the question. Cheers! \$\endgroup\$