Loading...
Searching...
No Matches
stagedata.sas
Go to the documentation of this file.
1/**
2 @file
3 @brief Sends a changeset to staging area
4 @details This is the service that is called when submitting a new edit.
5
6 <h4> Service Inputs </h4>
7 <h5> jsdata </h5>
8 This is the staged data table, plus an _____DELETE__THIS__RECORD_____ column
9
10 <h5> SASControlTable </h5>
11
12 |ACTION:$char4.|MESSAGE:$char1.|LIBDS:$char19.|
13 |---|---|---|
14 |LOAD|User-Provided message|LIBREF.DATASET_NAME|
15
16 <h4> SAS Macros </h4>
17 @li mf_getuser.sas
18 @li mf_nobs.sas
19 @li dc_assignlib.sas
20 @li mf_verifymacvars.sas
21 @li mf_mkdir.sas
22 @li mf_getuniquefileref.sas
23 @li mpe_loader.sas
24 @li mpe_filtermaster.sas
25 @li mp_abort.sas
26 @li mp_binarycopy.sas
27 @li mp_cntlout.sas
28 @li mp_ds2csv.sas
29 @li mp_validatecol.sas
30 @li mf_getplatform.sas
31 @li removecolsfromwork.sas
32 @li mpeinit.sas
33
34
35 @version 9.2
36 @author 4GL Apps Ltd
37 @copyright 4GL Apps Ltd. This code may only be used within Data Controller
38 and may not be re-distributed or re-sold without the express permission of
39 4GL Apps Ltd.
40
41**/
42
43%mpeinit()
44
45%global approver; %let approver=;
46%global libref; %let libref=;
47%global dsn; %let dsn=;
48%global user; %let user=;
49%let user=%mf_getuser();
50
51/* load parameters */
52data _null_;
53 set work.sascontroltable;
54 call symputx('action',action);
55 /* sanitise message to prevent code injection */
56 message=compress(message, '&%;');
57 call symputx('message',message);
58 libds=upcase(libds);
59 call symputx('orig_libds',libds);
60 is_fmt=0;
61 if substr(cats(reverse(libds)),1,3)=:'CF-' then do;
62 libds=scan(libds,1,'-');
63 putlog "Format Catalog Captured";
64 libds='work.fmtextract';
65 call symputx('libds',libds);
66 is_fmt=1;
67 end;
68 else call symputx('libds',libds);
69 call symputx('is_fmt',is_fmt);
70 /* validate libds to prevent code injection */
71 %mp_validatecol(LIBDS,LIBDS,is_libds)
72 if is_libds=0 then do;
73 putlog 'ERR' 'OR: Invalid libds:' libds;
74 call symputx('bad_libds',1);
75 end;
76 else call symputx('bad_libds',0);
77 putlog (_all_)(=);
78run;
79
80%mp_abort(iftrue= (&bad_libds=1)
81 ,mac=&_program
82 ,msg=%str(Invalid libds supplied)
83)
84
85%mp_cntlout(
86 iftrue=(&is_fmt=1)
87 ,libcat=&orig_libds
88 ,fmtlist=0
89 ,cntlout=work.fmtextract
90)
91
92/* stream back meta info, further jquery calls will return col metadata and
93 actual data */
94%let libref=%upcase(%scan(&libds,1,.));
95%let dsn=%upcase(%scan(&libds,2,.));
96%dc_assignlib(WRITE,&libref)
97%mp_abort(iftrue= (&syscc ne 0)
98 ,mac=&_program
99 ,msg=%str(syscc=&syscc - unable to assign library &libref)
100)
101
102%mp_abort(
103 iftrue=(%mf_verifymacvars(mpelocapprovals libds)=0)
104 ,mac=&_program
105 ,msg=%str(Missing: mpelocapprovals libds)
106)
107
108%put Verify that the upload does not violate Row Level Security checks:;
109%mpe_filtermaster(ULOAD,&libds,
110 dclib=&mpelib,
111 outref=filtref,
112 outds=work.query
113)
114
115%mp_abort(iftrue= (&syscc ne 0)
116 ,mac=&_program
117 ,msg=%str(syscc=&syscc during filtering process)
118)
119
120/* prepare inverse query */
121%let tempref=%mf_getuniquefileref();
122data _null_;
123 infile filtref end=eof;
124 file &tempref;
125 if _n_=1 then put 'where not(';
126 input;
127 put _infile_;
128 if eof then put ')';
129run;
130/* apply the query */
131data work.badrecords;
132 set work.jsdata;
133 %inc &tempref/source2;;
134 putlog (_all_)(=);
135run;
136%mp_abort(iftrue= (%mf_nobs(work.badrecords)>0)
137 ,mac=&_program
138 ,msg=%str(
139 Security Problem - %mf_nobs(work.badrecords) unauthorised records submitted
140 )
141)
142
143PROC FORMAT;
144 picture yymmddhhmmss other='%0Y%0m%0d_%0H%0M%0S' (datatype=datetime);
145RUN;
146
147/**
148 * Create package folder and redirect the log
149 */
150
151/* create a dataset key (datetime plus 6 digit random number plus PID) */
152%let mperef=DC%left(%sysfunc(datetime(),B8601DT19.3))_%substr(
153 %sysfunc(ranuni(0)),3,6)_%substr(%str(&sysjobid ),1,4);
154
155/* get web url */
156%global url;
157%let url=localhost/SASStoredProcess;
158%let platform=%mf_getplatform();
159%put &=platform;
160data _null_;
161 length url $128;
162
163%macro stagedata();
164 %if &platform=SASVIYA %then %do;
165 if symexist('_baseurl') then do;
166 url=symget('_baseurl');
167 if subpad(url,length(url)-9,9)='SASStudio'
168 then url=substr(url,1,length(url)-11);
169 else url="&systcpiphostname/SASJobExecution";
170 end;
171 else url="&systcpiphostname/SASJobExecution";
172 %end;
173 %else %if &platform=SASMETA %then %do;
174 rc=METADATA_GETURI("Stored Process Web App",url);
175 %end;
176%mend stagedata;
177%stagedata()
178
179 call symputx('url',url);
180 putlog url=;
181run;
182
183/* Create package folder */
184%let dir=&mpelocapprovals/&mperef;
185%mf_mkdir(&dir)
186
187/* redirect the log */
188%put; %put; %put log is being redirected;
189%put to retrieve, visit this url:; %put;%put;
190%let url=&url?_program=%substr(&_program
191 ,1,%length(&_program)-9)getlog%str(&)table=&mperef;
192%put &url;
193
194%mp_abort(iftrue= (&syscc ne 0)
195 ,mac=&_program
196 ,msg=%str(syscc=&syscc prior to log redirection)
197)
198
199proc printto log="&dir/weblog.txt";run;
200options notes mprint;
201libname approve "&dir";
202
203/* take copy of webin file */
204data _null_;
205 if symexist('_WEBIN_FILEREF1') then ref=symget('_WEBIN_FILEREF1');
206 else if symexist('sasjs_tables') then ref='0ref'; /* no fileref created */
207 else ref='indata1';
208 call symputx('ref',ref);
209 putlog ref=;
210run;
211
212%mp_binarycopy(inref=&ref,outloc="&dir/_WEBIN_FILEREF1.txt",iftrue=&ref ne 0ref)
213
214
215/* take copy of macvars */
216data _null_;
217 file "&dir/macvars.sas";
218 set sashelp.vmacro;
219 where scope='GLOBAL';
220 put '%let ' name '=' value ';';
221run;
222
223data approve.jsdset;
224 length _____DELETE__THIS__RECORD_____ $3;
225 set jsdata;
226run;
227
228/**
229 * mf_getvarXXX functions will fail if the target is locked - so take a copy
230 * and reference that (this will also explicitly throw the lock situation)
231 */
232%let dscopy=work.dscopy;
233data &dscopy;
234 set &libds;
235 stop;
236run;
237%mp_abort(iftrue= (&syscc ne 0)
238 ,mac=&_program
239 ,msg=%str(Issue getting lock on &libds)
240)
241
242%mp_ds2csv(approve.jsdset
243 ,dlm=COMMA
244 ,outfile="&dir/&orig_libds..csv"
245 ,outencoding="UTF-8"
246 ,headerformat=NAME
247 ,termstr=CRLF
248)
249
250%mp_abort(iftrue= (&syscc ne 0)
251 ,mac=&_program
252 ,msg=%str(syscc=&syscc when writing the CSV)
253)
254
255%mpe_loader(mperef=&mperef
256 ,submitted_reason_txt=%superq(message)
257 ,approver=%quote(%trim(&approver))
258 ,url=%superq(url)
259 ,dc_dttmtfmt=&dc_dttmtfmt
260)
261/* mp_abort cannot exit cleanly from inside a %include, so an abort there
262 (eg in a hook script run via mp_include) only records the error in
263 work.mp_abort_errds. mode=INCLUDE picks that up and aborts properly here. */
264%mp_abort(mode=INCLUDE)
265
266%mp_abort(iftrue= (&syscc ne 0)
267 ,mac=&_program..sas
268 ,msg=%str(syscc=&syscc)
269)
270
271/* send relevant SUCCESS values */
272data sasparams;
273STATUS='SUCCESS';
274DSID="&mperef";
275url="&url";
276run;
277
278%removecolsfromwork(___TMP___MD5)
279
280%webout(OPEN)
281%webout(OBJ,sasparams)
282%webout(CLOSE)
283
284%mpeterm()