1
0
mirror of https://github.com/sasjs/core.git synced 2026-01-09 18:30:06 +00:00

Compare commits

...

4 Commits

Author SHA1 Message Date
Allan Bowe
f0a5d89016 build.sh build on 2022-02-24:21:33:11 2022-02-24 21:33:11 +00:00
Allan Bowe
07bde4b25c feat: adding consul_token option as parameter in mv_registerclient. Closes #177 2022-02-24 21:16:23 +00:00
Allan Bowe
80b06af581 Merge pull request #176 from sasjs/streamserver
feat: adding SASjs server support to mp_streamfile.sas
2022-02-23 19:02:37 +02:00
Allan Bowe
3c026811e9 feat: adding SASjs server support to mp_streamfile.sas 2022-02-23 17:01:50 +00:00
6 changed files with 209 additions and 112 deletions

1
CNAME Normal file
View File

@@ -0,0 +1 @@
core.sasjs.io

158
all.sas
View File

@@ -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!;
@@ -23104,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]
@@ -23128,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
@@ -23184,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
@@ -23195,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);
@@ -23234,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;

View File

@@ -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!;

2
package-lock.json generated
View File

@@ -7,7 +7,7 @@
"name": "@sasjs/core", "name": "@sasjs/core",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@sasjs/cli": "3.6.0", "@sasjs/cli": "^3.6.0",
"@sasjs/core": "4.4.7" "@sasjs/core": "4.4.7"
} }
}, },

View File

@@ -33,7 +33,7 @@
"prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true" "prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true"
}, },
"devDependencies": { "devDependencies": {
"@sasjs/cli": "3.6.0", "@sasjs/cli": "^3.6.0",
"@sasjs/core": "4.4.7" "@sasjs/core": "4.4.7"
} }
} }

View File

@@ -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;