mirror of
https://github.com/sasjs/core.git
synced 2026-01-05 00:20:05 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
427deca350 | ||
|
|
07bde4b25c | ||
|
|
80b06af581 | ||
|
|
3c026811e9 | ||
|
|
cf547ce7e4 | ||
|
|
6952c79899 | ||
|
|
09e3f63da7 | ||
|
|
d6956f4122 | ||
|
|
6fca73e7da | ||
|
|
880df4138c | ||
|
|
b174aa25b3 | ||
|
|
bc6eac6977 | ||
|
|
2d4d595e5d | ||
|
|
7111fe14fb |
332
all.sas
332
all.sas
@@ -11271,6 +11271,7 @@ create table &outds as
|
|||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_getplatform.sas
|
@li mf_getplatform.sas
|
||||||
|
@li mfs_httpheader.sas
|
||||||
@li mp_binarycopy.sas
|
@li mp_binarycopy.sas
|
||||||
|
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
@@ -11304,7 +11305,7 @@ data _null_;
|
|||||||
run;
|
run;
|
||||||
|
|
||||||
%if &contentype=CSV %then %do;
|
%if &contentype=CSV %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/csv');
|
rc=stpsrv_header('Content-type','application/csv');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
@@ -11315,10 +11316,14 @@ run;
|
|||||||
contenttype='application/csv'
|
contenttype='application/csv'
|
||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type,application/csv)
|
||||||
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=EXCEL %then %do;
|
%else %if &contentype=EXCEL %then %do;
|
||||||
/* suitable for XLS format */
|
/* suitable for XLS format */
|
||||||
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/vnd.ms-excel');
|
rc=stpsrv_header('Content-type','application/vnd.ms-excel');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
@@ -11329,9 +11334,13 @@ run;
|
|||||||
contenttype='application/vnd.ms-excel'
|
contenttype='application/vnd.ms-excel'
|
||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type,application/vnd.ms-excel)
|
||||||
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=GIF or &contentype=JPEG or &contentype=PNG %then %do;
|
%else %if &contentype=GIF or &contentype=JPEG or &contentype=PNG %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',"image/%lowcase(&contenttype)");
|
rc=stpsrv_header('Content-type',"image/%lowcase(&contenttype)");
|
||||||
run;
|
run;
|
||||||
@@ -11340,15 +11349,21 @@ run;
|
|||||||
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI"
|
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI"
|
||||||
contenttype="image/%lowcase(&contenttype)";
|
contenttype="image/%lowcase(&contenttype)";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type,image/%lowcase(&contenttype))
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=HTML %then %do;
|
%else %if &contentype=HTML %then %do;
|
||||||
%if &platform=SASVIYA %then %do;
|
%if &platform=SASVIYA %then %do;
|
||||||
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json"
|
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json"
|
||||||
contenttype="text/html";
|
contenttype="text/html";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type,text/html)
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=TEXT %then %do;
|
%else %if &contentype=TEXT %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/text');
|
rc=stpsrv_header('Content-type','application/text');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
@@ -11359,9 +11374,13 @@ run;
|
|||||||
contenttype='application/text'
|
contenttype='application/text'
|
||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type,application/text)
|
||||||
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=WOFF or &contentype=WOFF2 or &contentype=TTF %then %do;
|
%else %if &contentype=WOFF or &contentype=WOFF2 or &contentype=TTF %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',"font/%lowcase(&contenttype)");
|
rc=stpsrv_header('Content-type',"font/%lowcase(&contenttype)");
|
||||||
run;
|
run;
|
||||||
@@ -11370,9 +11389,12 @@ run;
|
|||||||
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI"
|
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI"
|
||||||
contenttype="font/%lowcase(&contenttype)";
|
contenttype="font/%lowcase(&contenttype)";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type,font/%lowcase(&contenttype))
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=XLSX %then %do;
|
%else %if &contentype=XLSX %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',
|
rc=stpsrv_header('Content-type',
|
||||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||||
@@ -11385,9 +11407,15 @@ run;
|
|||||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type
|
||||||
|
,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||||
|
)
|
||||||
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=ZIP %then %do;
|
%else %if &contentype=ZIP %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/zip');
|
rc=stpsrv_header('Content-type','application/zip');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
@@ -11398,6 +11426,10 @@ run;
|
|||||||
contenttype='application/zip'
|
contenttype='application/zip'
|
||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type,application/zip)
|
||||||
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
%put %str(ERR)OR: Content Type &contenttype NOT SUPPORTED by &sysmacroname!;
|
%put %str(ERR)OR: Content Type &contenttype NOT SUPPORTED by &sysmacroname!;
|
||||||
@@ -13550,13 +13582,14 @@ run;
|
|||||||
The macro is idempotent - if you run it twice, it will only create a folder
|
The macro is idempotent - if you run it twice, it will only create a folder
|
||||||
once.
|
once.
|
||||||
|
|
||||||
usage:
|
Usage:
|
||||||
|
|
||||||
%mm_createfolder(path=/some/meta/folder)
|
%mm_createfolder(path=/some/meta/folder)
|
||||||
|
|
||||||
@param [in] path= Name of the folder to create.
|
@param [in] path= Name of the folder to create.
|
||||||
@param [in] mdebug= set DBG to 1 to disable DEBUG messages
|
@param [in] mdebug= set DBG to 1 to disable DEBUG messages
|
||||||
|
|
||||||
|
|
||||||
@version 9.4
|
@version 9.4
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
|
|
||||||
@@ -14032,7 +14065,7 @@ filename &frefout temp;
|
|||||||
This macro is idempotent - if you run it twice, it will only create an STP
|
This macro is idempotent - if you run it twice, it will only create an STP
|
||||||
once.
|
once.
|
||||||
|
|
||||||
usage (type 1 STP):
|
Usage (type 1 STP):
|
||||||
|
|
||||||
%mm_createstp(stpname=MyNewSTP
|
%mm_createstp(stpname=MyNewSTP
|
||||||
,filename=mySpecialProgram.sas
|
,filename=mySpecialProgram.sas
|
||||||
@@ -14051,7 +14084,8 @@ filename &frefout temp;
|
|||||||
putlog (_all_)(=);
|
putlog (_all_)(=);
|
||||||
run;
|
run;
|
||||||
|
|
||||||
usage (type 2 STP):
|
Usage (type 2 STP):
|
||||||
|
|
||||||
%mm_createstp(stpname=MyNewType2STP
|
%mm_createstp(stpname=MyNewType2STP
|
||||||
,filename=mySpecialProgram.sas
|
,filename=mySpecialProgram.sas
|
||||||
,directory=SASEnvironment/SASCode/STPs
|
,directory=SASEnvironment/SASCode/STPs
|
||||||
@@ -14094,8 +14128,9 @@ filename &frefout temp;
|
|||||||
@li mf_verifymacvars.sas
|
@li mf_verifymacvars.sas
|
||||||
@li mm_getdirectories.sas
|
@li mm_getdirectories.sas
|
||||||
@li mm_updatestpsourcecode.sas
|
@li mm_updatestpsourcecode.sas
|
||||||
@li mp_dropmembers.sas
|
|
||||||
@li mm_getservercontexts.sas
|
@li mm_getservercontexts.sas
|
||||||
|
@li mp_abort.sas
|
||||||
|
@li mp_dropmembers.sas
|
||||||
|
|
||||||
<h4> Related Macros </h4>
|
<h4> Related Macros </h4>
|
||||||
@li mm_createwebservice.sas
|
@li mm_createwebservice.sas
|
||||||
@@ -15174,17 +15209,22 @@ run;
|
|||||||
%mend mm_deletestp;
|
%mend mm_deletestp;
|
||||||
/**
|
/**
|
||||||
@file mm_getauthinfo.sas
|
@file mm_getauthinfo.sas
|
||||||
@brief extracts authentication info
|
@brief Extracts authentication info for each user in metadata
|
||||||
@details usage:
|
@details
|
||||||
|
Usage:
|
||||||
|
|
||||||
%mm_getauthinfo(outds=auths)
|
%mm_getauthinfo(outds=auths)
|
||||||
|
|
||||||
@param outds= the ONE LEVEL work dataset to create
|
|
||||||
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages and preserve outputs
|
||||||
|
@param [out] outds= (mm_getauthinfo) The output dataset to create
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mm_getobjects.sas
|
|
||||||
@li mf_getuniquefileref.sas
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mf_getuniquename.sas
|
||||||
@li mm_getdetails.sas
|
@li mm_getdetails.sas
|
||||||
|
@li mm_getobjects.sas
|
||||||
|
|
||||||
|
|
||||||
@version 9.4
|
@version 9.4
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
@@ -15192,67 +15232,69 @@ run;
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mm_getauthinfo(outds=mm_getauthinfo
|
%macro mm_getauthinfo(outds=mm_getauthinfo
|
||||||
|
,mdebug=0
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
%local prefix fileref;
|
||||||
|
%let prefix=%substr(%mf_getuniquename(),1,25);
|
||||||
|
|
||||||
%if %length(&outds)>30 %then %do;
|
%mm_getobjects(type=Login,outds=&prefix.0)
|
||||||
%put %str(ERR)OR: Temp tables are created with the &outds prefix, which
|
|
||||||
therefore needs to be 30 characters or less;
|
|
||||||
%return;
|
|
||||||
%end;
|
|
||||||
%if %index(&outds,'.')>0 %then %do;
|
|
||||||
%put %str(ERR)OR: Table &outds should be ONE LEVEL (no library);
|
|
||||||
%return;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
%mm_getobjects(type=Login,outds=&outds.0)
|
|
||||||
|
|
||||||
%local fileref;
|
%local fileref;
|
||||||
%let fileref=%mf_getuniquefileref();
|
%let fileref=%mf_getuniquefileref();
|
||||||
|
|
||||||
data _null_;
|
data _null_;
|
||||||
file &fileref;
|
file &fileref;
|
||||||
set &outds.0 end=last;
|
set &prefix.0 end=last;
|
||||||
/* run macro */
|
/* run macro */
|
||||||
str=cats('%mm_getdetails(uri=',id,",outattrs=&outds.d",_n_
|
str=cats('%mm_getdetails(uri=',id,",outattrs=&prefix.d",_n_
|
||||||
,",outassocs=&outds.a",_n_,")");
|
,",outassocs=&prefix.a",_n_,")");
|
||||||
put str;
|
put str;
|
||||||
/* transpose attributes */
|
/* transpose attributes */
|
||||||
str=cats("proc transpose data=&outds.d",_n_,"(drop=type) out=&outds.da"
|
str=cats("proc transpose data=&prefix.d",_n_,"(drop=type) out=&prefix.da"
|
||||||
,_n_,"(drop=_name_);var value;id name;run;");
|
,_n_,"(drop=_name_);var value;id name;run;");
|
||||||
put str;
|
put str;
|
||||||
/* add extra info to attributes */
|
/* add extra info to attributes */
|
||||||
str=cats("data &outds.da",_n_,";length login_id login_name $256; login_id="
|
str=cats("data &prefix.da",_n_,";length login_id login_name $256; login_id="
|
||||||
,quote(trim(id)),";set &outds.da",_n_
|
,quote(trim(id)),";set &prefix.da",_n_
|
||||||
,";login_name=trim(subpad(name,1,256));drop name;run;");
|
,";login_name=trim(subpad(name,1,256));drop name;run;");
|
||||||
put str;
|
put str;
|
||||||
/* add extra info to associations */
|
/* add extra info to associations */
|
||||||
str=cats("data &outds.a",_n_,";length login_id login_name $256; login_id="
|
str=cats("data &prefix.a",_n_,";length login_id login_name $256; login_id="
|
||||||
,quote(trim(id)),";login_name=",quote(trim(name))
|
,quote(trim(id)),";login_name=",quote(trim(name))
|
||||||
,";set &outds.a",_n_,";run;");
|
,";set &prefix.a",_n_,";run;");
|
||||||
put str;
|
put str;
|
||||||
if last then do;
|
if last then do;
|
||||||
/* collate attributes */
|
/* collate attributes */
|
||||||
str=cats("data &outds._logat; set &outds.da1-&outds.da",_n_,";run;");
|
str=cats("data &prefix._logat; set &prefix.da1-&prefix.da",_n_,";run;");
|
||||||
put str;
|
put str;
|
||||||
/* collate associations */
|
/* collate associations */
|
||||||
str=cats("data &outds._logas; set &outds.a1-&outds.a",_n_,";run;");
|
str=cats("data &prefix._logas; set &prefix.a1-&prefix.a",_n_,";run;");
|
||||||
put str;
|
put str;
|
||||||
/* tidy up */
|
/* tidy up */
|
||||||
str=cats("proc delete data=&outds.da1-&outds.da",_n_,";run;");
|
str=cats("proc delete data=&prefix.da1-&prefix.da",_n_,";run;");
|
||||||
put str;
|
put str;
|
||||||
str=cats("proc delete data=&outds.d1-&outds.d",_n_,";run;");
|
str=cats("proc delete data=&prefix.d1-&prefix.d",_n_,";run;");
|
||||||
put str;
|
put str;
|
||||||
str=cats("proc delete data=&outds.a1-&outds.a",_n_,";run;");
|
str=cats("proc delete data=&prefix.a1-&prefix.a",_n_,";run;");
|
||||||
put str;
|
put str;
|
||||||
end;
|
end;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
data _null_;
|
||||||
|
infile &fileref;
|
||||||
|
if _n_=1 then putlog // "Now executing the following code:" //;
|
||||||
|
input; putlog _infile_;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
%inc &fileref;
|
%inc &fileref;
|
||||||
|
filename &fileref clear;
|
||||||
|
|
||||||
/* get libraries */
|
/* get libraries */
|
||||||
proc sort data=&outds._logas(where=(assoc='Libraries')) out=&outds._temp;
|
proc sort data=&prefix._logas(where=(assoc='Libraries')) out=&prefix._temp;
|
||||||
by login_id;
|
by login_id;
|
||||||
data &outds._temp;
|
data &prefix._temp;
|
||||||
set &outds._temp;
|
set &prefix._temp;
|
||||||
by login_id;
|
by login_id;
|
||||||
length library_list $32767;
|
length library_list $32767;
|
||||||
retain library_list;
|
retain library_list;
|
||||||
@@ -15260,32 +15302,28 @@ data &outds._temp;
|
|||||||
else library_list=catx(' !! ',library_list,name);
|
else library_list=catx(' !! ',library_list,name);
|
||||||
proc sql;
|
proc sql;
|
||||||
/* get auth domain */
|
/* get auth domain */
|
||||||
create table &outds._dom as
|
create table &prefix._dom as
|
||||||
select login_id,name as domain
|
select login_id,name as domain
|
||||||
from &outds._logas
|
from &prefix._logas
|
||||||
where assoc='Domain';
|
where assoc='Domain';
|
||||||
create unique index login_id on &outds._dom(login_id);
|
create unique index login_id on &prefix._dom(login_id);
|
||||||
/* join it all together */
|
/* join it all together */
|
||||||
create table &outds._logins as
|
create table &outds as
|
||||||
select a.*
|
select a.*
|
||||||
,c.domain
|
,c.domain
|
||||||
,b.library_list
|
,b.library_list
|
||||||
from &outds._logat (drop=ishidden lockedby usageversion publictype) a
|
from &prefix._logat (drop=ishidden lockedby usageversion publictype) a
|
||||||
left join &outds._temp b
|
left join &prefix._temp b
|
||||||
on a.login_id=b.login_id
|
on a.login_id=b.login_id
|
||||||
left join &outds._dom c
|
left join &prefix._dom c
|
||||||
on a.login_id=c.login_id;
|
on a.login_id=c.login_id;
|
||||||
drop table &outds._temp;
|
|
||||||
drop table &outds._logat;
|
|
||||||
drop table &outds._logas;
|
|
||||||
|
|
||||||
data _null_;
|
%if &mdebug=0 %then %do;
|
||||||
infile &fileref;
|
proc datasets lib=work;
|
||||||
if _n_=1 then putlog // "Now executing the following code:" //;
|
delete &prefix:;
|
||||||
input; putlog _infile_;
|
run;
|
||||||
run;
|
%end;
|
||||||
|
|
||||||
filename &fileref clear;
|
|
||||||
|
|
||||||
%mend mm_getauthinfo;/**
|
%mend mm_getauthinfo;/**
|
||||||
@file
|
@file
|
||||||
@@ -18499,6 +18537,58 @@ run;
|
|||||||
%inc &fref1;
|
%inc &fref1;
|
||||||
|
|
||||||
%mend mmx_spkexport;/**
|
%mend mmx_spkexport;/**
|
||||||
|
@file
|
||||||
|
@brief Sets the http headers in the SASjs/server response
|
||||||
|
@details For GET requests, SASjs server will use the file generated by this
|
||||||
|
macro for setting the appropriate http headers in the response.
|
||||||
|
|
||||||
|
It works by writing a file to the session directory, that is then ingested by
|
||||||
|
the server.
|
||||||
|
|
||||||
|
The location of this file is driven by the global variable
|
||||||
|
`sasjs_stpsrv_header_loc` which is made available in the autoexec.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
%mfs_httpheader(Content-type,application/csv)
|
||||||
|
|
||||||
|
@param [in] header_name Name of the http header to set
|
||||||
|
@param [in] header_value Value of the http header to set
|
||||||
|
|
||||||
|
<h4> Related Macros </h4>
|
||||||
|
@li mcf_stpsrv_header.sas
|
||||||
|
|
||||||
|
@version 9.3
|
||||||
|
@author Allan Bowe
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mfs_httpheader(header_name
|
||||||
|
,header_value
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
%local fref fid i;
|
||||||
|
|
||||||
|
%if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc)) ne 0 %then %do;
|
||||||
|
%put &=fref &=sasjs_stpsrv_header_loc;
|
||||||
|
%put %str(ERR)OR: %sysfunc(sysmsg());
|
||||||
|
%return;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%let fid=%sysfunc(fopen(&fref,A));
|
||||||
|
|
||||||
|
%if &fid=0 %then %do;
|
||||||
|
%put %str(ERR)OR: %sysfunc(sysmsg());
|
||||||
|
%return;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%let rc=%sysfunc(fput(&fid,%str(&header_name): %str(&header_value)));
|
||||||
|
%let rc=%sysfunc(fwrite(&fid));
|
||||||
|
|
||||||
|
%let rc=%sysfunc(fclose(&fid));
|
||||||
|
%let rc=%sysfunc(filename(&fref));
|
||||||
|
|
||||||
|
%mend mfs_httpheader;
|
||||||
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Send data to/from @sasjs/server
|
@brief Send data to/from @sasjs/server
|
||||||
@details This macro should be added to the start of each web service,
|
@details This macro should be added to the start of each web service,
|
||||||
@@ -18533,8 +18623,9 @@ run;
|
|||||||
`,"$tablename":{"formats":{"col1":"$CHAR1"},"types":{"COL1":"C"}}`
|
`,"$tablename":{"formats":{"col1":"$CHAR1"},"types":{"COL1":"C"}}`
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mp_jsonout.sas
|
|
||||||
@li mf_getuser.sas
|
@li mf_getuser.sas
|
||||||
|
@li mp_jsonout.sas
|
||||||
|
@li mfs_httpheader.sas
|
||||||
|
|
||||||
<h4> Related Macros </h4>
|
<h4> Related Macros </h4>
|
||||||
@li mv_webout.sas
|
@li mv_webout.sas
|
||||||
@@ -18586,11 +18677,11 @@ run;
|
|||||||
/* fix encoding */
|
/* fix encoding */
|
||||||
OPTIONS NOBOMFILE;
|
OPTIONS NOBOMFILE;
|
||||||
|
|
||||||
|
/* set the header */
|
||||||
|
%mfs_httpheader(Content-type,application/json)
|
||||||
|
|
||||||
/* setup json */
|
/* setup json */
|
||||||
data _null_;file &fref encoding='utf-8' termstr=lf;
|
data _null_;file &fref encoding='utf-8' termstr=lf;
|
||||||
%if %str(&_debug) ge 131 %then %do;
|
|
||||||
put '>>weboutBEGIN<<';
|
|
||||||
%end;
|
|
||||||
put '{"SYSDATE" : "' "&SYSDATE" '"';
|
put '{"SYSDATE" : "' "&SYSDATE" '"';
|
||||||
put ',"SYSTIME" : "' "&SYSTIME" '"';
|
put ',"SYSTIME" : "' "&SYSTIME" '"';
|
||||||
run;
|
run;
|
||||||
@@ -18670,9 +18761,6 @@ run;
|
|||||||
memsize=quote(cats(memsize));
|
memsize=quote(cats(memsize));
|
||||||
put ',"MEMSIZE" : ' memsize;
|
put ',"MEMSIZE" : ' memsize;
|
||||||
put "}" @;
|
put "}" @;
|
||||||
%if %str(&_debug) ge 131 %then %do;
|
|
||||||
put '>>weboutEND<<';
|
|
||||||
%end;
|
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
@@ -23048,10 +23136,10 @@ run;
|
|||||||
%mend mv_jobwaitfor;/**
|
%mend mv_jobwaitfor;/**
|
||||||
@file mv_registerclient.sas
|
@file mv_registerclient.sas
|
||||||
@brief Register Client and Secret (admin task)
|
@brief Register Client and Secret (admin task)
|
||||||
@details When building apps on SAS Viya, an client id and secret are sometimes
|
@details When building apps on SAS Viya, a client id and secret are usually
|
||||||
required. In order to generate them, filesystem access to the Consul Token
|
required. In order to generate them, the Consul Token is required. To access
|
||||||
is needed (it is not enough to be in the SASAdministrator group in SAS
|
this token, you need to be a system administrator (it is not enough to be in
|
||||||
Environment Manager).
|
the SASAdministrator group in SAS Environment Manager).
|
||||||
|
|
||||||
If you are registering a lot of clients / secrets, you may find it more
|
If you are registering a lot of clients / secrets, you may find it more
|
||||||
convenient to use the [Viya Token Generator]
|
convenient to use the [Viya Token Generator]
|
||||||
@@ -23072,51 +23160,56 @@ run;
|
|||||||
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||||
%inc mc;
|
%inc mc;
|
||||||
|
|
||||||
|
%* generate random client using consul token as input parameter;
|
||||||
|
%mv_registerclient(consul_token=12x34sa43v2345n234lasd)
|
||||||
|
|
||||||
|
%* generate random client details with all scopes;
|
||||||
|
%mv_registerclient(scopes=openid *)
|
||||||
|
|
||||||
%* specific client with just openid scope;
|
%* specific client with just openid scope;
|
||||||
%mv_registerclient(client_id=YourClient
|
%mv_registerclient(client_id=YourClient
|
||||||
,client_secret=YourSecret
|
,client_secret=YourSecret
|
||||||
,scopes=openid
|
,scopes=openid
|
||||||
)
|
)
|
||||||
|
|
||||||
%* generate random client details with all scopes;
|
|
||||||
%mv_registerclient(scopes=openid *)
|
|
||||||
|
|
||||||
%* generate random client with 90/180 second access/refresh token expiry;
|
%* generate random client with 90/180 second access/refresh token expiry;
|
||||||
%mv_registerclient(scopes=openid *
|
%mv_registerclient(scopes=openid *
|
||||||
,access_token_validity=90
|
,access_token_validity=90
|
||||||
,refresh_token_validity=180
|
,refresh_token_validity=180
|
||||||
)
|
)
|
||||||
|
|
||||||
@param client_id= The client name. Auto generated if blank.
|
@param [in,out] client_id= The client name. Auto generated if blank.
|
||||||
@param client_secret= Client secret. Auto generated if client is blank.
|
@param [in,out] client_secret= Client secret. Auto generated if client is
|
||||||
@param scopes=(openid) List of space-seperated unquoted scopes
|
blank.
|
||||||
@param grant_type=(authorization_code|refresh_token) Valid values are
|
@param [in] consul_token= (0) Provide the actual consul token value here if
|
||||||
"password" or "authorization_code" (unquoted)
|
using Viya 4 or above.
|
||||||
@param outds=(mv_registerclient) The dataset to contain the registered client
|
@param [in] scopes= (openid) List of space-seperated unquoted scopes
|
||||||
id and secret
|
@param [in] grant_type= (authorization_code|refresh_token) Valid values are
|
||||||
@param access_token_validity=(DEFAULT) The duration of validity of the access
|
"password" or "authorization_code" (unquoted). Pipe seperated.
|
||||||
token in seconds. A value of DEFAULT will omit the entry (and use system
|
@param [out] outds=(mv_registerclient) The dataset to contain the registered
|
||||||
default)
|
client id and secret
|
||||||
@param refresh_token_validity=(DEFAULT) The duration of validity of the
|
@param [in] access_token_validity= (DEFAULT) The access token duration in
|
||||||
|
seconds. A value of DEFAULT will omit the entry (and use system default)
|
||||||
|
@param [in] refresh_token_validity= (DEFAULT) The duration of validity of the
|
||||||
refresh token in seconds. A value of DEFAULT will omit the entry (and use
|
refresh token in seconds. A value of DEFAULT will omit the entry (and use
|
||||||
system default)
|
system default)
|
||||||
@param name= An optional, human readable name for the client
|
@param [in] client_name= (DEFAULT) An optional, human readable name for the
|
||||||
@param required_user_groups= A list of group names. If a user does not belong
|
client.
|
||||||
to all the required groups, the user will not be authenticated and no tokens
|
@param [in] required_user_groups= A list of group names. If a user does not
|
||||||
are issued to this client for that user. If this field is not specified,
|
belong to all the required groups, the user will not be authenticated and no
|
||||||
authentication and token issuance proceeds normally.
|
tokens are issued to this client for that user. If this field is not
|
||||||
@param autoapprove= During the auth step the user can choose which scope to
|
specified, authentication and token issuance proceeds normally.
|
||||||
apply. Setting this to true will autoapprove all the client scopes.
|
@param [in] autoapprove= During the auth step the user can choose which scope
|
||||||
@param use_session= If true, access tokens issued to this client will be
|
to apply. Setting this to true will autoapprove all the client scopes.
|
||||||
|
@param [in] use_session= If true, access tokens issued to this client will be
|
||||||
associated with an HTTP session and revoked upon logout or time-out.
|
associated with an HTTP session and revoked upon logout or time-out.
|
||||||
@param outjson= (_null_) A dataset containing the lines of JSON submitted.
|
@param [out] outjson= (_null_) A dataset containing the lines of JSON
|
||||||
Useful for debugging.
|
submitted. Useful for debugging.
|
||||||
|
|
||||||
@version VIYA V.03.04
|
@version VIYA V.03.04
|
||||||
@author Allan Bowe, source: https://github.com/sasjs/core
|
@author Allan Bowe, source: https://github.com/sasjs/core
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mp_abort.sas
|
|
||||||
@li mf_getplatform.sas
|
@li mf_getplatform.sas
|
||||||
@li mf_getuniquefileref.sas
|
@li mf_getuniquefileref.sas
|
||||||
@li mf_getuniquelibref.sas
|
@li mf_getuniquelibref.sas
|
||||||
@@ -23128,6 +23221,7 @@ run;
|
|||||||
|
|
||||||
%macro mv_registerclient(client_id=
|
%macro mv_registerclient(client_id=
|
||||||
,client_secret=
|
,client_secret=
|
||||||
|
,consul_token=0
|
||||||
,client_name=DEFAULT
|
,client_name=DEFAULT
|
||||||
,scopes=openid
|
,scopes=openid
|
||||||
,grant_type=authorization_code|refresh_token
|
,grant_type=authorization_code|refresh_token
|
||||||
@@ -23139,33 +23233,40 @@ run;
|
|||||||
,refresh_token_validity=DEFAULT
|
,refresh_token_validity=DEFAULT
|
||||||
,outjson=_null_
|
,outjson=_null_
|
||||||
);
|
);
|
||||||
%local consul_token fname1 fname2 fname3 libref access_token url tokloc;
|
%local fname1 fname2 fname3 libref access_token url tokloc;
|
||||||
|
|
||||||
%if client_name=DEFAULT %then %let client_name=
|
%if client_name=DEFAULT %then %let client_name=
|
||||||
Generated by %mf_getuser() on %sysfunc(datetime(),datetime19.) using SASjs;
|
Generated by %mf_getuser() (&sysuserid) on %sysfunc(datetime(),datetime19.
|
||||||
|
) using SASjs;
|
||||||
|
|
||||||
options noquotelenmax;
|
options noquotelenmax;
|
||||||
/* first, get consul token needed to get client id / secret */
|
|
||||||
%let tokloc=/etc/SASSecurityCertificateFramework/tokens/consul/default;
|
|
||||||
%let tokloc=%mf_loc(VIYACONFIG)&tokloc/client.token;
|
|
||||||
|
|
||||||
|
%if "&consul_token"="0" %then %do;
|
||||||
|
/* first, get consul token needed to get client id / secret */
|
||||||
|
%let tokloc=/etc/SASSecurityCertificateFramework/tokens/consul/default;
|
||||||
|
%let tokloc=%mf_loc(VIYACONFIG)&tokloc/client.token;
|
||||||
|
|
||||||
%mp_abort(iftrue=(%sysfunc(fileexist(&tokloc))=0)
|
%if %sysfunc(fileexist(&tokloc))=0 %then %do;
|
||||||
,mac=&sysmacroname
|
%put &sysmacroname: unable to access the consul token at &tokloc;
|
||||||
,msg=%str(Unable to access the consul token at &tokloc)
|
%put Try passing the value in the consul= macro parameter;
|
||||||
)
|
%put See docs: https://core.sasjs.io/mv__registerclient_8sas.html;
|
||||||
|
%abort;
|
||||||
|
%end;
|
||||||
|
|
||||||
%let consul_token=0;
|
data _null_;
|
||||||
data _null_;
|
infile "&tokloc";
|
||||||
infile "&tokloc";
|
input token:$64.;
|
||||||
input token:$64.;
|
call symputx('consul_token',token);
|
||||||
call symputx('consul_token',token);
|
run;
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_abort(iftrue=("&consul_token"="0")
|
%if "&consul_token"="0" %then %do;
|
||||||
,mac=&sysmacroname
|
%put &sysmacroname: Unable to source the consul token from &tokloc;
|
||||||
,msg=%str(Unable to source the consul token from &tokloc)
|
%put It seems your account (&sysuserid) does not have admin rights;
|
||||||
)
|
%put Please speak with your platform adminstrator;
|
||||||
|
%put Docs: https://core.sasjs.io/mv__registerclient_8sas.html;
|
||||||
|
%abort;
|
||||||
|
%end;
|
||||||
|
%end;
|
||||||
|
|
||||||
%local base_uri; /* location of rest apis */
|
%local base_uri; /* location of rest apis */
|
||||||
%let base_uri=%mf_getplatform(VIYARESTAPI);
|
%let base_uri=%mf_getplatform(VIYARESTAPI);
|
||||||
@@ -23178,6 +23279,9 @@ proc http method='POST' out=&fname1
|
|||||||
headers "X-Consul-Token"="&consul_token";
|
headers "X-Consul-Token"="&consul_token";
|
||||||
run;
|
run;
|
||||||
|
|
||||||
|
%put &=SYS_PROCHTTP_STATUS_CODE;
|
||||||
|
%put &=SYS_PROCHTTP_STATUS_PHRASE;
|
||||||
|
|
||||||
%let libref=%mf_getuniquelibref();
|
%let libref=%mf_getuniquelibref();
|
||||||
libname &libref JSON fileref=&fname1;
|
libname &libref JSON fileref=&fname1;
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_getplatform.sas
|
@li mf_getplatform.sas
|
||||||
|
@li mfs_httpheader.sas
|
||||||
@li mp_binarycopy.sas
|
@li mp_binarycopy.sas
|
||||||
|
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
@@ -55,7 +56,7 @@ data _null_;
|
|||||||
run;
|
run;
|
||||||
|
|
||||||
%if &contentype=CSV %then %do;
|
%if &contentype=CSV %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/csv');
|
rc=stpsrv_header('Content-type','application/csv');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
@@ -66,10 +67,14 @@ run;
|
|||||||
contenttype='application/csv'
|
contenttype='application/csv'
|
||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type,application/csv)
|
||||||
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=EXCEL %then %do;
|
%else %if &contentype=EXCEL %then %do;
|
||||||
/* suitable for XLS format */
|
/* suitable for XLS format */
|
||||||
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/vnd.ms-excel');
|
rc=stpsrv_header('Content-type','application/vnd.ms-excel');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
@@ -80,9 +85,13 @@ run;
|
|||||||
contenttype='application/vnd.ms-excel'
|
contenttype='application/vnd.ms-excel'
|
||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type,application/vnd.ms-excel)
|
||||||
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=GIF or &contentype=JPEG or &contentype=PNG %then %do;
|
%else %if &contentype=GIF or &contentype=JPEG or &contentype=PNG %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',"image/%lowcase(&contenttype)");
|
rc=stpsrv_header('Content-type',"image/%lowcase(&contenttype)");
|
||||||
run;
|
run;
|
||||||
@@ -91,15 +100,21 @@ run;
|
|||||||
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI"
|
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI"
|
||||||
contenttype="image/%lowcase(&contenttype)";
|
contenttype="image/%lowcase(&contenttype)";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type,image/%lowcase(&contenttype))
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=HTML %then %do;
|
%else %if &contentype=HTML %then %do;
|
||||||
%if &platform=SASVIYA %then %do;
|
%if &platform=SASVIYA %then %do;
|
||||||
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json"
|
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json"
|
||||||
contenttype="text/html";
|
contenttype="text/html";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type,text/html)
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=TEXT %then %do;
|
%else %if &contentype=TEXT %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/text');
|
rc=stpsrv_header('Content-type','application/text');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
@@ -110,9 +125,13 @@ run;
|
|||||||
contenttype='application/text'
|
contenttype='application/text'
|
||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type,application/text)
|
||||||
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=WOFF or &contentype=WOFF2 or &contentype=TTF %then %do;
|
%else %if &contentype=WOFF or &contentype=WOFF2 or &contentype=TTF %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',"font/%lowcase(&contenttype)");
|
rc=stpsrv_header('Content-type',"font/%lowcase(&contenttype)");
|
||||||
run;
|
run;
|
||||||
@@ -121,9 +140,12 @@ run;
|
|||||||
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI"
|
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI"
|
||||||
contenttype="font/%lowcase(&contenttype)";
|
contenttype="font/%lowcase(&contenttype)";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type,font/%lowcase(&contenttype))
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=XLSX %then %do;
|
%else %if &contentype=XLSX %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',
|
rc=stpsrv_header('Content-type',
|
||||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||||
@@ -136,9 +158,15 @@ run;
|
|||||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type
|
||||||
|
,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||||
|
)
|
||||||
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=ZIP %then %do;
|
%else %if &contentype=ZIP %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/zip');
|
rc=stpsrv_header('Content-type','application/zip');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
@@ -149,6 +177,10 @@ run;
|
|||||||
contenttype='application/zip'
|
contenttype='application/zip'
|
||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
|
%else %if &platform=SASJS %then %do;
|
||||||
|
%mfs_httpheader(Content-type,application/zip)
|
||||||
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
%put %str(ERR)OR: Content Type &contenttype NOT SUPPORTED by &sysmacroname!;
|
%put %str(ERR)OR: Content Type &contenttype NOT SUPPORTED by &sysmacroname!;
|
||||||
|
|||||||
@@ -12,13 +12,14 @@
|
|||||||
The macro is idempotent - if you run it twice, it will only create a folder
|
The macro is idempotent - if you run it twice, it will only create a folder
|
||||||
once.
|
once.
|
||||||
|
|
||||||
usage:
|
Usage:
|
||||||
|
|
||||||
%mm_createfolder(path=/some/meta/folder)
|
%mm_createfolder(path=/some/meta/folder)
|
||||||
|
|
||||||
@param [in] path= Name of the folder to create.
|
@param [in] path= Name of the folder to create.
|
||||||
@param [in] mdebug= set DBG to 1 to disable DEBUG messages
|
@param [in] mdebug= set DBG to 1 to disable DEBUG messages
|
||||||
|
|
||||||
|
|
||||||
@version 9.4
|
@version 9.4
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
This macro is idempotent - if you run it twice, it will only create an STP
|
This macro is idempotent - if you run it twice, it will only create an STP
|
||||||
once.
|
once.
|
||||||
|
|
||||||
usage (type 1 STP):
|
Usage (type 1 STP):
|
||||||
|
|
||||||
%mm_createstp(stpname=MyNewSTP
|
%mm_createstp(stpname=MyNewSTP
|
||||||
,filename=mySpecialProgram.sas
|
,filename=mySpecialProgram.sas
|
||||||
@@ -31,7 +31,8 @@
|
|||||||
putlog (_all_)(=);
|
putlog (_all_)(=);
|
||||||
run;
|
run;
|
||||||
|
|
||||||
usage (type 2 STP):
|
Usage (type 2 STP):
|
||||||
|
|
||||||
%mm_createstp(stpname=MyNewType2STP
|
%mm_createstp(stpname=MyNewType2STP
|
||||||
,filename=mySpecialProgram.sas
|
,filename=mySpecialProgram.sas
|
||||||
,directory=SASEnvironment/SASCode/STPs
|
,directory=SASEnvironment/SASCode/STPs
|
||||||
@@ -74,8 +75,9 @@
|
|||||||
@li mf_verifymacvars.sas
|
@li mf_verifymacvars.sas
|
||||||
@li mm_getdirectories.sas
|
@li mm_getdirectories.sas
|
||||||
@li mm_updatestpsourcecode.sas
|
@li mm_updatestpsourcecode.sas
|
||||||
@li mp_dropmembers.sas
|
|
||||||
@li mm_getservercontexts.sas
|
@li mm_getservercontexts.sas
|
||||||
|
@li mp_abort.sas
|
||||||
|
@li mp_dropmembers.sas
|
||||||
|
|
||||||
<h4> Related Macros </h4>
|
<h4> Related Macros </h4>
|
||||||
@li mm_createwebservice.sas
|
@li mm_createwebservice.sas
|
||||||
|
|||||||
@@ -1,16 +1,21 @@
|
|||||||
/**
|
/**
|
||||||
@file mm_getauthinfo.sas
|
@file mm_getauthinfo.sas
|
||||||
@brief extracts authentication info
|
@brief Extracts authentication info for each user in metadata
|
||||||
@details usage:
|
@details
|
||||||
|
Usage:
|
||||||
|
|
||||||
%mm_getauthinfo(outds=auths)
|
%mm_getauthinfo(outds=auths)
|
||||||
|
|
||||||
@param outds= the ONE LEVEL work dataset to create
|
|
||||||
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages and preserve outputs
|
||||||
|
@param [out] outds= (mm_getauthinfo) The output dataset to create
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mm_getobjects.sas
|
|
||||||
@li mf_getuniquefileref.sas
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mf_getuniquename.sas
|
||||||
@li mm_getdetails.sas
|
@li mm_getdetails.sas
|
||||||
|
@li mm_getobjects.sas
|
||||||
|
|
||||||
|
|
||||||
@version 9.4
|
@version 9.4
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
@@ -18,67 +23,69 @@
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mm_getauthinfo(outds=mm_getauthinfo
|
%macro mm_getauthinfo(outds=mm_getauthinfo
|
||||||
|
,mdebug=0
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
%local prefix fileref;
|
||||||
|
%let prefix=%substr(%mf_getuniquename(),1,25);
|
||||||
|
|
||||||
%if %length(&outds)>30 %then %do;
|
%mm_getobjects(type=Login,outds=&prefix.0)
|
||||||
%put %str(ERR)OR: Temp tables are created with the &outds prefix, which
|
|
||||||
therefore needs to be 30 characters or less;
|
|
||||||
%return;
|
|
||||||
%end;
|
|
||||||
%if %index(&outds,'.')>0 %then %do;
|
|
||||||
%put %str(ERR)OR: Table &outds should be ONE LEVEL (no library);
|
|
||||||
%return;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
%mm_getobjects(type=Login,outds=&outds.0)
|
|
||||||
|
|
||||||
%local fileref;
|
%local fileref;
|
||||||
%let fileref=%mf_getuniquefileref();
|
%let fileref=%mf_getuniquefileref();
|
||||||
|
|
||||||
data _null_;
|
data _null_;
|
||||||
file &fileref;
|
file &fileref;
|
||||||
set &outds.0 end=last;
|
set &prefix.0 end=last;
|
||||||
/* run macro */
|
/* run macro */
|
||||||
str=cats('%mm_getdetails(uri=',id,",outattrs=&outds.d",_n_
|
str=cats('%mm_getdetails(uri=',id,",outattrs=&prefix.d",_n_
|
||||||
,",outassocs=&outds.a",_n_,")");
|
,",outassocs=&prefix.a",_n_,")");
|
||||||
put str;
|
put str;
|
||||||
/* transpose attributes */
|
/* transpose attributes */
|
||||||
str=cats("proc transpose data=&outds.d",_n_,"(drop=type) out=&outds.da"
|
str=cats("proc transpose data=&prefix.d",_n_,"(drop=type) out=&prefix.da"
|
||||||
,_n_,"(drop=_name_);var value;id name;run;");
|
,_n_,"(drop=_name_);var value;id name;run;");
|
||||||
put str;
|
put str;
|
||||||
/* add extra info to attributes */
|
/* add extra info to attributes */
|
||||||
str=cats("data &outds.da",_n_,";length login_id login_name $256; login_id="
|
str=cats("data &prefix.da",_n_,";length login_id login_name $256; login_id="
|
||||||
,quote(trim(id)),";set &outds.da",_n_
|
,quote(trim(id)),";set &prefix.da",_n_
|
||||||
,";login_name=trim(subpad(name,1,256));drop name;run;");
|
,";login_name=trim(subpad(name,1,256));drop name;run;");
|
||||||
put str;
|
put str;
|
||||||
/* add extra info to associations */
|
/* add extra info to associations */
|
||||||
str=cats("data &outds.a",_n_,";length login_id login_name $256; login_id="
|
str=cats("data &prefix.a",_n_,";length login_id login_name $256; login_id="
|
||||||
,quote(trim(id)),";login_name=",quote(trim(name))
|
,quote(trim(id)),";login_name=",quote(trim(name))
|
||||||
,";set &outds.a",_n_,";run;");
|
,";set &prefix.a",_n_,";run;");
|
||||||
put str;
|
put str;
|
||||||
if last then do;
|
if last then do;
|
||||||
/* collate attributes */
|
/* collate attributes */
|
||||||
str=cats("data &outds._logat; set &outds.da1-&outds.da",_n_,";run;");
|
str=cats("data &prefix._logat; set &prefix.da1-&prefix.da",_n_,";run;");
|
||||||
put str;
|
put str;
|
||||||
/* collate associations */
|
/* collate associations */
|
||||||
str=cats("data &outds._logas; set &outds.a1-&outds.a",_n_,";run;");
|
str=cats("data &prefix._logas; set &prefix.a1-&prefix.a",_n_,";run;");
|
||||||
put str;
|
put str;
|
||||||
/* tidy up */
|
/* tidy up */
|
||||||
str=cats("proc delete data=&outds.da1-&outds.da",_n_,";run;");
|
str=cats("proc delete data=&prefix.da1-&prefix.da",_n_,";run;");
|
||||||
put str;
|
put str;
|
||||||
str=cats("proc delete data=&outds.d1-&outds.d",_n_,";run;");
|
str=cats("proc delete data=&prefix.d1-&prefix.d",_n_,";run;");
|
||||||
put str;
|
put str;
|
||||||
str=cats("proc delete data=&outds.a1-&outds.a",_n_,";run;");
|
str=cats("proc delete data=&prefix.a1-&prefix.a",_n_,";run;");
|
||||||
put str;
|
put str;
|
||||||
end;
|
end;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
data _null_;
|
||||||
|
infile &fileref;
|
||||||
|
if _n_=1 then putlog // "Now executing the following code:" //;
|
||||||
|
input; putlog _infile_;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
%inc &fileref;
|
%inc &fileref;
|
||||||
|
filename &fileref clear;
|
||||||
|
|
||||||
/* get libraries */
|
/* get libraries */
|
||||||
proc sort data=&outds._logas(where=(assoc='Libraries')) out=&outds._temp;
|
proc sort data=&prefix._logas(where=(assoc='Libraries')) out=&prefix._temp;
|
||||||
by login_id;
|
by login_id;
|
||||||
data &outds._temp;
|
data &prefix._temp;
|
||||||
set &outds._temp;
|
set &prefix._temp;
|
||||||
by login_id;
|
by login_id;
|
||||||
length library_list $32767;
|
length library_list $32767;
|
||||||
retain library_list;
|
retain library_list;
|
||||||
@@ -86,31 +93,27 @@ data &outds._temp;
|
|||||||
else library_list=catx(' !! ',library_list,name);
|
else library_list=catx(' !! ',library_list,name);
|
||||||
proc sql;
|
proc sql;
|
||||||
/* get auth domain */
|
/* get auth domain */
|
||||||
create table &outds._dom as
|
create table &prefix._dom as
|
||||||
select login_id,name as domain
|
select login_id,name as domain
|
||||||
from &outds._logas
|
from &prefix._logas
|
||||||
where assoc='Domain';
|
where assoc='Domain';
|
||||||
create unique index login_id on &outds._dom(login_id);
|
create unique index login_id on &prefix._dom(login_id);
|
||||||
/* join it all together */
|
/* join it all together */
|
||||||
create table &outds._logins as
|
create table &outds as
|
||||||
select a.*
|
select a.*
|
||||||
,c.domain
|
,c.domain
|
||||||
,b.library_list
|
,b.library_list
|
||||||
from &outds._logat (drop=ishidden lockedby usageversion publictype) a
|
from &prefix._logat (drop=ishidden lockedby usageversion publictype) a
|
||||||
left join &outds._temp b
|
left join &prefix._temp b
|
||||||
on a.login_id=b.login_id
|
on a.login_id=b.login_id
|
||||||
left join &outds._dom c
|
left join &prefix._dom c
|
||||||
on a.login_id=c.login_id;
|
on a.login_id=c.login_id;
|
||||||
drop table &outds._temp;
|
|
||||||
drop table &outds._logat;
|
|
||||||
drop table &outds._logas;
|
|
||||||
|
|
||||||
data _null_;
|
%if &mdebug=0 %then %do;
|
||||||
infile &fileref;
|
proc datasets lib=work;
|
||||||
if _n_=1 then putlog // "Now executing the following code:" //;
|
delete &prefix:;
|
||||||
input; putlog _infile_;
|
run;
|
||||||
run;
|
%end;
|
||||||
|
|
||||||
filename &fileref clear;
|
|
||||||
|
|
||||||
%mend mm_getauthinfo;
|
%mend mm_getauthinfo;
|
||||||
12
package-lock.json
generated
12
package-lock.json
generated
@@ -1150,9 +1150,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.14.7",
|
"version": "1.14.8",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
|
||||||
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==",
|
"integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3678,9 +3678,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"follow-redirects": {
|
"follow-redirects": {
|
||||||
"version": "1.14.7",
|
"version": "1.14.8",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
|
||||||
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==",
|
"integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"form-data": {
|
"form-data": {
|
||||||
|
|||||||
52
server/mfs_httpheader.sas
Normal file
52
server/mfs_httpheader.sas
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Sets the http headers in the SASjs/server response
|
||||||
|
@details For GET requests, SASjs server will use the file generated by this
|
||||||
|
macro for setting the appropriate http headers in the response.
|
||||||
|
|
||||||
|
It works by writing a file to the session directory, that is then ingested by
|
||||||
|
the server.
|
||||||
|
|
||||||
|
The location of this file is driven by the global variable
|
||||||
|
`sasjs_stpsrv_header_loc` which is made available in the autoexec.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
%mfs_httpheader(Content-type,application/csv)
|
||||||
|
|
||||||
|
@param [in] header_name Name of the http header to set
|
||||||
|
@param [in] header_value Value of the http header to set
|
||||||
|
|
||||||
|
<h4> Related Macros </h4>
|
||||||
|
@li mcf_stpsrv_header.sas
|
||||||
|
|
||||||
|
@version 9.3
|
||||||
|
@author Allan Bowe
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mfs_httpheader(header_name
|
||||||
|
,header_value
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
%local fref fid i;
|
||||||
|
|
||||||
|
%if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc)) ne 0 %then %do;
|
||||||
|
%put &=fref &=sasjs_stpsrv_header_loc;
|
||||||
|
%put %str(ERR)OR: %sysfunc(sysmsg());
|
||||||
|
%return;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%let fid=%sysfunc(fopen(&fref,A));
|
||||||
|
|
||||||
|
%if &fid=0 %then %do;
|
||||||
|
%put %str(ERR)OR: %sysfunc(sysmsg());
|
||||||
|
%return;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%let rc=%sysfunc(fput(&fid,%str(&header_name): %str(&header_value)));
|
||||||
|
%let rc=%sysfunc(fwrite(&fid));
|
||||||
|
|
||||||
|
%let rc=%sysfunc(fclose(&fid));
|
||||||
|
%let rc=%sysfunc(filename(&fref));
|
||||||
|
|
||||||
|
%mend mfs_httpheader;
|
||||||
@@ -33,8 +33,9 @@
|
|||||||
`,"$tablename":{"formats":{"col1":"$CHAR1"},"types":{"COL1":"C"}}`
|
`,"$tablename":{"formats":{"col1":"$CHAR1"},"types":{"COL1":"C"}}`
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mp_jsonout.sas
|
|
||||||
@li mf_getuser.sas
|
@li mf_getuser.sas
|
||||||
|
@li mp_jsonout.sas
|
||||||
|
@li mfs_httpheader.sas
|
||||||
|
|
||||||
<h4> Related Macros </h4>
|
<h4> Related Macros </h4>
|
||||||
@li mv_webout.sas
|
@li mv_webout.sas
|
||||||
@@ -86,11 +87,11 @@
|
|||||||
/* fix encoding */
|
/* fix encoding */
|
||||||
OPTIONS NOBOMFILE;
|
OPTIONS NOBOMFILE;
|
||||||
|
|
||||||
|
/* set the header */
|
||||||
|
%mfs_httpheader(Content-type,application/json)
|
||||||
|
|
||||||
/* setup json */
|
/* setup json */
|
||||||
data _null_;file &fref encoding='utf-8' termstr=lf;
|
data _null_;file &fref encoding='utf-8' termstr=lf;
|
||||||
%if %str(&_debug) ge 131 %then %do;
|
|
||||||
put '>>weboutBEGIN<<';
|
|
||||||
%end;
|
|
||||||
put '{"SYSDATE" : "' "&SYSDATE" '"';
|
put '{"SYSDATE" : "' "&SYSDATE" '"';
|
||||||
put ',"SYSTIME" : "' "&SYSTIME" '"';
|
put ',"SYSTIME" : "' "&SYSTIME" '"';
|
||||||
run;
|
run;
|
||||||
@@ -170,9 +171,6 @@
|
|||||||
memsize=quote(cats(memsize));
|
memsize=quote(cats(memsize));
|
||||||
put ',"MEMSIZE" : ' memsize;
|
put ',"MEMSIZE" : ' memsize;
|
||||||
put "}" @;
|
put "}" @;
|
||||||
%if %str(&_debug) ge 131 %then %do;
|
|
||||||
put '>>weboutEND<<';
|
|
||||||
%end;
|
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
|
|||||||
21
tests/sas9only/mm_getauthinfo.test.sas
Normal file
21
tests/sas9only/mm_getauthinfo.test.sas
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing mm_getauthinfo macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_existds.sas
|
||||||
|
@li mm_getauthinfo.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%mm_getauthinfo(outds=auths)
|
||||||
|
%mp_assertscope(COMPARE)
|
||||||
|
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%mf_existds(work.auths)=1),
|
||||||
|
desc=Check if the auths dataset was created
|
||||||
|
)
|
||||||
48
tests/serveronly/mfs_httpheader.test.sas
Normal file
48
tests/serveronly/mfs_httpheader.test.sas
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing mfs_httpheader.sas macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mfs_httpheader.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/header.txt;
|
||||||
|
|
||||||
|
%mfs_httpheader(Content-type,application/csv)
|
||||||
|
data _null_;
|
||||||
|
infile "&sasjs_stpsrv_header_loc";
|
||||||
|
input;
|
||||||
|
if _n_=1 then call symputx('test1',_infile_);
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&syscc=0),
|
||||||
|
desc=Check code ran without errors,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&test1"="Content-type: application/csv"),
|
||||||
|
desc=Checking line was created,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
%mfs_httpheader(Content-type,application/text)
|
||||||
|
%let test2=0;
|
||||||
|
data _null_;
|
||||||
|
infile "&sasjs_stpsrv_header_loc";
|
||||||
|
input;
|
||||||
|
if _n_=2 then call symputx('test2',_infile_);
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&syscc=0),
|
||||||
|
desc=Check code ran without errors for test2,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&test2"="Content-type: application/text"),
|
||||||
|
desc=Checking line was created,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
/**
|
/**
|
||||||
@file mv_registerclient.sas
|
@file mv_registerclient.sas
|
||||||
@brief Register Client and Secret (admin task)
|
@brief Register Client and Secret (admin task)
|
||||||
@details When building apps on SAS Viya, an client id and secret are sometimes
|
@details When building apps on SAS Viya, a client id and secret are usually
|
||||||
required. In order to generate them, filesystem access to the Consul Token
|
required. In order to generate them, the Consul Token is required. To access
|
||||||
is needed (it is not enough to be in the SASAdministrator group in SAS
|
this token, you need to be a system administrator (it is not enough to be in
|
||||||
Environment Manager).
|
the SASAdministrator group in SAS Environment Manager).
|
||||||
|
|
||||||
If you are registering a lot of clients / secrets, you may find it more
|
If you are registering a lot of clients / secrets, you may find it more
|
||||||
convenient to use the [Viya Token Generator]
|
convenient to use the [Viya Token Generator]
|
||||||
@@ -25,51 +25,56 @@
|
|||||||
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||||
%inc mc;
|
%inc mc;
|
||||||
|
|
||||||
|
%* generate random client using consul token as input parameter;
|
||||||
|
%mv_registerclient(consul_token=12x34sa43v2345n234lasd)
|
||||||
|
|
||||||
|
%* generate random client details with all scopes;
|
||||||
|
%mv_registerclient(scopes=openid *)
|
||||||
|
|
||||||
%* specific client with just openid scope;
|
%* specific client with just openid scope;
|
||||||
%mv_registerclient(client_id=YourClient
|
%mv_registerclient(client_id=YourClient
|
||||||
,client_secret=YourSecret
|
,client_secret=YourSecret
|
||||||
,scopes=openid
|
,scopes=openid
|
||||||
)
|
)
|
||||||
|
|
||||||
%* generate random client details with all scopes;
|
|
||||||
%mv_registerclient(scopes=openid *)
|
|
||||||
|
|
||||||
%* generate random client with 90/180 second access/refresh token expiry;
|
%* generate random client with 90/180 second access/refresh token expiry;
|
||||||
%mv_registerclient(scopes=openid *
|
%mv_registerclient(scopes=openid *
|
||||||
,access_token_validity=90
|
,access_token_validity=90
|
||||||
,refresh_token_validity=180
|
,refresh_token_validity=180
|
||||||
)
|
)
|
||||||
|
|
||||||
@param client_id= The client name. Auto generated if blank.
|
@param [in,out] client_id= The client name. Auto generated if blank.
|
||||||
@param client_secret= Client secret. Auto generated if client is blank.
|
@param [in,out] client_secret= Client secret. Auto generated if client is
|
||||||
@param scopes=(openid) List of space-seperated unquoted scopes
|
blank.
|
||||||
@param grant_type=(authorization_code|refresh_token) Valid values are
|
@param [in] consul_token= (0) Provide the actual consul token value here if
|
||||||
"password" or "authorization_code" (unquoted)
|
using Viya 4 or above.
|
||||||
@param outds=(mv_registerclient) The dataset to contain the registered client
|
@param [in] scopes= (openid) List of space-seperated unquoted scopes
|
||||||
id and secret
|
@param [in] grant_type= (authorization_code|refresh_token) Valid values are
|
||||||
@param access_token_validity=(DEFAULT) The duration of validity of the access
|
"password" or "authorization_code" (unquoted). Pipe seperated.
|
||||||
token in seconds. A value of DEFAULT will omit the entry (and use system
|
@param [out] outds=(mv_registerclient) The dataset to contain the registered
|
||||||
default)
|
client id and secret
|
||||||
@param refresh_token_validity=(DEFAULT) The duration of validity of the
|
@param [in] access_token_validity= (DEFAULT) The access token duration in
|
||||||
|
seconds. A value of DEFAULT will omit the entry (and use system default)
|
||||||
|
@param [in] refresh_token_validity= (DEFAULT) The duration of validity of the
|
||||||
refresh token in seconds. A value of DEFAULT will omit the entry (and use
|
refresh token in seconds. A value of DEFAULT will omit the entry (and use
|
||||||
system default)
|
system default)
|
||||||
@param name= An optional, human readable name for the client
|
@param [in] client_name= (DEFAULT) An optional, human readable name for the
|
||||||
@param required_user_groups= A list of group names. If a user does not belong
|
client.
|
||||||
to all the required groups, the user will not be authenticated and no tokens
|
@param [in] required_user_groups= A list of group names. If a user does not
|
||||||
are issued to this client for that user. If this field is not specified,
|
belong to all the required groups, the user will not be authenticated and no
|
||||||
authentication and token issuance proceeds normally.
|
tokens are issued to this client for that user. If this field is not
|
||||||
@param autoapprove= During the auth step the user can choose which scope to
|
specified, authentication and token issuance proceeds normally.
|
||||||
apply. Setting this to true will autoapprove all the client scopes.
|
@param [in] autoapprove= During the auth step the user can choose which scope
|
||||||
@param use_session= If true, access tokens issued to this client will be
|
to apply. Setting this to true will autoapprove all the client scopes.
|
||||||
|
@param [in] use_session= If true, access tokens issued to this client will be
|
||||||
associated with an HTTP session and revoked upon logout or time-out.
|
associated with an HTTP session and revoked upon logout or time-out.
|
||||||
@param outjson= (_null_) A dataset containing the lines of JSON submitted.
|
@param [out] outjson= (_null_) A dataset containing the lines of JSON
|
||||||
Useful for debugging.
|
submitted. Useful for debugging.
|
||||||
|
|
||||||
@version VIYA V.03.04
|
@version VIYA V.03.04
|
||||||
@author Allan Bowe, source: https://github.com/sasjs/core
|
@author Allan Bowe, source: https://github.com/sasjs/core
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mp_abort.sas
|
|
||||||
@li mf_getplatform.sas
|
@li mf_getplatform.sas
|
||||||
@li mf_getuniquefileref.sas
|
@li mf_getuniquefileref.sas
|
||||||
@li mf_getuniquelibref.sas
|
@li mf_getuniquelibref.sas
|
||||||
@@ -81,6 +86,7 @@
|
|||||||
|
|
||||||
%macro mv_registerclient(client_id=
|
%macro mv_registerclient(client_id=
|
||||||
,client_secret=
|
,client_secret=
|
||||||
|
,consul_token=0
|
||||||
,client_name=DEFAULT
|
,client_name=DEFAULT
|
||||||
,scopes=openid
|
,scopes=openid
|
||||||
,grant_type=authorization_code|refresh_token
|
,grant_type=authorization_code|refresh_token
|
||||||
@@ -92,33 +98,40 @@
|
|||||||
,refresh_token_validity=DEFAULT
|
,refresh_token_validity=DEFAULT
|
||||||
,outjson=_null_
|
,outjson=_null_
|
||||||
);
|
);
|
||||||
%local consul_token fname1 fname2 fname3 libref access_token url tokloc;
|
%local fname1 fname2 fname3 libref access_token url tokloc;
|
||||||
|
|
||||||
%if client_name=DEFAULT %then %let client_name=
|
%if client_name=DEFAULT %then %let client_name=
|
||||||
Generated by %mf_getuser() on %sysfunc(datetime(),datetime19.) using SASjs;
|
Generated by %mf_getuser() (&sysuserid) on %sysfunc(datetime(),datetime19.
|
||||||
|
) using SASjs;
|
||||||
|
|
||||||
options noquotelenmax;
|
options noquotelenmax;
|
||||||
/* first, get consul token needed to get client id / secret */
|
|
||||||
%let tokloc=/etc/SASSecurityCertificateFramework/tokens/consul/default;
|
|
||||||
%let tokloc=%mf_loc(VIYACONFIG)&tokloc/client.token;
|
|
||||||
|
|
||||||
|
%if "&consul_token"="0" %then %do;
|
||||||
|
/* first, get consul token needed to get client id / secret */
|
||||||
|
%let tokloc=/etc/SASSecurityCertificateFramework/tokens/consul/default;
|
||||||
|
%let tokloc=%mf_loc(VIYACONFIG)&tokloc/client.token;
|
||||||
|
|
||||||
%mp_abort(iftrue=(%sysfunc(fileexist(&tokloc))=0)
|
%if %sysfunc(fileexist(&tokloc))=0 %then %do;
|
||||||
,mac=&sysmacroname
|
%put &sysmacroname: unable to access the consul token at &tokloc;
|
||||||
,msg=%str(Unable to access the consul token at &tokloc)
|
%put Try passing the value in the consul= macro parameter;
|
||||||
)
|
%put See docs: https://core.sasjs.io/mv__registerclient_8sas.html;
|
||||||
|
%abort;
|
||||||
|
%end;
|
||||||
|
|
||||||
%let consul_token=0;
|
data _null_;
|
||||||
data _null_;
|
infile "&tokloc";
|
||||||
infile "&tokloc";
|
input token:$64.;
|
||||||
input token:$64.;
|
call symputx('consul_token',token);
|
||||||
call symputx('consul_token',token);
|
run;
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_abort(iftrue=("&consul_token"="0")
|
%if "&consul_token"="0" %then %do;
|
||||||
,mac=&sysmacroname
|
%put &sysmacroname: Unable to source the consul token from &tokloc;
|
||||||
,msg=%str(Unable to source the consul token from &tokloc)
|
%put It seems your account (&sysuserid) does not have admin rights;
|
||||||
)
|
%put Please speak with your platform adminstrator;
|
||||||
|
%put Docs: https://core.sasjs.io/mv__registerclient_8sas.html;
|
||||||
|
%abort;
|
||||||
|
%end;
|
||||||
|
%end;
|
||||||
|
|
||||||
%local base_uri; /* location of rest apis */
|
%local base_uri; /* location of rest apis */
|
||||||
%let base_uri=%mf_getplatform(VIYARESTAPI);
|
%let base_uri=%mf_getplatform(VIYARESTAPI);
|
||||||
@@ -131,6 +144,9 @@ proc http method='POST' out=&fname1
|
|||||||
headers "X-Consul-Token"="&consul_token";
|
headers "X-Consul-Token"="&consul_token";
|
||||||
run;
|
run;
|
||||||
|
|
||||||
|
%put &=SYS_PROCHTTP_STATUS_CODE;
|
||||||
|
%put &=SYS_PROCHTTP_STATUS_PHRASE;
|
||||||
|
|
||||||
%let libref=%mf_getuniquelibref();
|
%let libref=%mf_getuniquelibref();
|
||||||
libname &libref JSON fileref=&fname1;
|
libname &libref JSON fileref=&fname1;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user