diff --git a/.gitpod.yml b/.gitpod.yml
index 8b02b22..549bf82 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -5,4 +5,4 @@ image:
file: .gitpod.dockerfile
vscode:
extensions:
- - sasjs.sasjs-for-vscode@1.6.0:V4hJpMtbpekMcPRNhh4SXQ==
\ No newline at end of file
+ - sasjs.sasjs-for-vscode@1.7.2:R6y1nzpFh2P99BZg5FgH5g==
\ No newline at end of file
diff --git a/.sasjslint b/.sasjslint
new file mode 100644
index 0000000..9de0cb1
--- /dev/null
+++ b/.sasjslint
@@ -0,0 +1,10 @@
+{
+ "noTrailingSpaces": true,
+ "noEncodedPasswords": true,
+ "hasDoxygenHeader": true,
+ "noSpacesInFileNames": true,
+ "maxLineLength": 120,
+ "lowerCaseFileNames": true,
+ "noTabIndentation": true,
+ "indentationMultiple": 2
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index f98ba8e..94746be 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@ Documentation: https://core.sasjs.io
- X command enabled
- Prefixes: _mmw_,_mmu_,_mmx_
-**lua** library
+**lua** library
Wait - this is a macro library - what is LUA doing here? Well, it is a little known fact that you CAN run LUA within a SAS Macro. It has to be written to a text file with a `.lua` extension, from where you can `%include` it. So, without using the `proc lua` wrapper.
@@ -51,7 +51,7 @@ To contribute, simply write your freeform LUA in the LUA folder. Then run the `
%ml_yourmodule()
/* Execute. Do not use the restart keyword! */
-proc lua;
+proc lua;
submit;
print(yourStuff);
endsubmit;
@@ -118,7 +118,7 @@ All macros must be commented in the doxygen format, to enable the [online docume
### Dependencies
SAS code can contain one of two types of dependency - SAS Macros, and SAS Programs. When compiling projects using the [SASjs CLI](https://cli.sasjs.io) the doxygen header is scanned for ` @li` items under the following headers:
-```
+```sas
SAS Macros
@li mf_nobs.sas
@li mm_assignlib.sas
diff --git a/viya/mv_getjoblog.sas b/viya/mv_getjoblog.sas
index 860928e..b72c553 100644
--- a/viya/mv_getjoblog.sas
+++ b/viya/mv_getjoblog.sas
@@ -10,7 +10,8 @@
First, compile the macros:
- filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
+ filename mc url
+ "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc;
Next, create a job (in this case, a web service):
@@ -174,7 +175,7 @@ data _null_;
outfile:write(logloc)
io.close(infile)
io.close(outfile)
- ';
+ ';
run;
%inc "&fpath3..lua";
/* get log path*/
@@ -228,7 +229,7 @@ data _null_;
io.input(infile)
local resp=json.decode(io.read())
for i, v in pairs(resp["items"]) do
- outfile:write(v.line,"\n")
+ outfile:write(v.line,"\n")
end
io.close(infile)
io.close(outfile)
diff --git a/viya/mv_getrefreshtoken.sas b/viya/mv_getrefreshtoken.sas
index d7b7904..82ecf39 100644
--- a/viya/mv_getrefreshtoken.sas
+++ b/viya/mv_getrefreshtoken.sas
@@ -1,24 +1,24 @@
- /**
- @file mv_getrefreshtoken.sas
- @brief deprecated - replaced by mv_tokenauth.sas
+/**
+ @file mv_getrefreshtoken.sas
+ @brief deprecated - replaced by mv_tokenauth.sas
- @version VIYA V.03.04
- @author Allan Bowe, source: https://github.com/sasjs/core
+ @version VIYA V.03.04
+ @author Allan Bowe, source: https://github.com/sasjs/core
- SAS Macros
- @li mv_tokenauth.sas
+ SAS Macros
+ @li mv_tokenauth.sas
- **/
+**/
- %macro mv_getrefreshtoken(client_id=someclient
- ,client_secret=somesecret
- ,grant_type=authorization_code
- ,code=
- ,user=
- ,pass=
- ,access_token_var=ACCESS_TOKEN
- ,refresh_token_var=REFRESH_TOKEN
- );
+%macro mv_getrefreshtoken(client_id=someclient
+ ,client_secret=somesecret
+ ,grant_type=authorization_code
+ ,code=
+ ,user=
+ ,pass=
+ ,access_token_var=ACCESS_TOKEN
+ ,refresh_token_var=REFRESH_TOKEN
+ );
%mv_tokenauth(client_id=&client_id
,client_secret=&client_secret
diff --git a/viya/mv_getusergroups.sas b/viya/mv_getusergroups.sas
index b67920c..72a4d21 100644
--- a/viya/mv_getusergroups.sas
+++ b/viya/mv_getusergroups.sas
@@ -65,7 +65,7 @@ proc http method='GET' out=&fname1 &oauth_bearer
url="&base_uri/identities/users/&user/memberships?limit=10000";
headers
%if &grant_type=authorization_code %then %do;
- "Authorization"="Bearer &&&access_token_var"
+ "Authorization"="Bearer &&&access_token_var"
%end;
"Accept"="application/json";
run;
diff --git a/viya/mv_getusers.sas b/viya/mv_getusers.sas
index bef7bf4..935df83 100644
--- a/viya/mv_getusers.sas
+++ b/viya/mv_getusers.sas
@@ -37,11 +37,11 @@
@param access_token_var= The global macro variable to contain the access token
@param grant_type= valid values:
- * password
- * authorization_code
- * detect - will check if access_token exists, if not will use sas_services if
- a SASStudioV session else authorization_code. Default option.
- * sas_services - will use oauth_bearer=sas_services
+ * password
+ * authorization_code
+ * detect - will check if access_token exists, if not will use sas_services if
+ a SASStudioV session else authorization_code. Default option.
+ * sas_services - will use oauth_bearer=sas_services
@param outds= The library.dataset to be created that contains the list of groups
diff --git a/viya/mv_jobflow.sas b/viya/mv_jobflow.sas
index 6b4142a..5f45d6b 100644
--- a/viya/mv_jobflow.sas
+++ b/viya/mv_jobflow.sas
@@ -13,7 +13,7 @@
@li FLOW_ID - Numeric value, provides sequential ordering capability. Is
optional, will default to 0 if not provided.
@li _CONTEXTNAME - Dictates which context should be used to run the job. If
- blank (or not provided), will default to `SAS Job Execution compute context`.
+ blank, or not provided, will default to `SAS Job Execution compute context`.
Any additional variables provided in this table are converted into macro
variables and passed into the relevant job.
@@ -97,15 +97,17 @@
run;
- @param [in] access_token_var= The global macro variable to contain the access token
+ @param [in] access_token_var= The global macro variable to contain the access
+ token
@param [in] grant_type= valid values:
@li password
@li authorization_code
- @li detect - will check if access_token exists, if not will use sas_services if
- a SASStudioV session else authorization_code. Default option.
+ @li detect - will check if access_token exists, if not will use
+ sas_services if a SASStudioV session else authorization_code. Default
+ option.
@li sas_services - will use oauth_bearer=sas_services
@param [in] inds= The input dataset containing a list of jobs and parameters
- @param [in] maxconcurrency= The max number of parallel jobs to run. Default=8.
+ @param [in] maxconcurrency= The max number of parallel jobs to run. Default=8.
@param [in] raise_err=0 Set to 1 to raise SYSCC when a job does not complete
succcessfully
@param [in] mdebug= set to 1 to enable DEBUG messages
@@ -185,7 +187,7 @@ select count(*) into: missings
where flow_id is null or _program is null;
%mp_abort(iftrue=(&missings>0)
,mac=&sysmacroname
- ,msg=%str(input dataset contains &missings missing values for FLOW_ID or _PROGRAM)
+ ,msg=%str(input dataset has &missings missing values for FLOW_ID or _PROGRAM)
)
%if %mf_nobs(&inds)=0 %then %do;
@@ -284,7 +286,8 @@ data;run;%let jdswaitfor=&syslast;
%if "&&jobuid&jid"="0" and &concurrency<&maxconcurrency %then %do;
%local jobname jobpath;
%let jobname=%scan(&&job&jid,-1,/);
- %let jobpath=%substr(&&job&jid,1,%length(&&job&jid)-%length(&jobname)-1);
+ %let jobpath=
+ %substr(&&job&jid,1,%length(&&job&jid)-%length(&jobname)-1);
%put executing &jobpath/&jobname with paramstring &&jparams&jid;
%mv_jobexecute(path=&jobpath
,name=&jobname
@@ -334,7 +337,8 @@ data;run;%let jdswaitfor=&syslast;
/* loop again if jobs are left */
%if &completed < &jcnt %then %do;
%let jid=0;
- %put looping flow &fid again - &completed of &jcnt jobs completed, &concurrency jobs running;
+ %put looping flow &fid again - &completed of &jcnt jobs completed,
+ &concurrency jobs running;
%end;
%end;
%end;
diff --git a/viya/mv_jobwaitfor.sas b/viya/mv_jobwaitfor.sas
index 9820903..4735f7c 100644
--- a/viya/mv_jobwaitfor.sas
+++ b/viya/mv_jobwaitfor.sas
@@ -225,7 +225,7 @@ run;
%else %let SYSCC=5;
%put %str(ERR)OR: Job &&jobname&i. did not complete successfully. &stateDetails;
%return;
- %end;
+ %end;
%end;
%end;
diff --git a/viya/mv_registerclient.sas b/viya/mv_registerclient.sas
index 9c2f585..a1fca07 100644
--- a/viya/mv_registerclient.sas
+++ b/viya/mv_registerclient.sas
@@ -4,15 +4,17 @@
@details When building apps on SAS Viya, an client id and secret is required.
This macro will obtain the Consul Token and use that to call the Web Service.
- more info: https://developer.sas.com/reference/auth/#register
- and: http://proc-x.com/2019/01/authentication-to-sas-viya-a-couple-of-approaches/
+ more info: https://developer.sas.com/reference/auth/#register
+ and:
+ http://proc-x.com/2019/01/authentication-to-sas-viya-a-couple-of-approaches
The default viyaroot location is /opt/sas/viya/config
Usage:
%* compile macros;
- filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
+ filename mc url
+ "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc;
%* specific client with just openid scope;
@@ -33,7 +35,8 @@
@param client_id= The client name. Auto generated if blank.
@param client_secret= Client secret Auto generated if client is blank.
@param scopes= list of space-seperated unquoted scopes (default is openid)
- @param grant_type= valid values are "password" or "authorization_code" (unquoted)
+ @param grant_type= valid values are "password" or "authorization_code"
+ (unquoted)
@param outds= the dataset to contain the registered client id and secret
@param access_token_validity= The duration of validity of the access token
in seconds. A value of DEFAULT will omit the entry (and use system default)
@@ -78,15 +81,16 @@
,refresh_token_validity=DEFAULT
,outjson=_null_
);
-%local consul_token fname1 fname2 fname3 libref access_token url;
+%local consul_token fname1 fname2 fname3 libref access_token url tokloc;
%if client_name=DEFAULT %then %let client_name=
Generated by %mf_getuser() on %sysfunc(datetime(),datetime19.) using SASjs;
options noquotelenmax;
/* first, get consul token needed to get client id / secret */
+%let tokloc=/etc/SASSecurityCertificateFramework/tokens/consul/default;
data _null_;
- infile "%mf_loc(VIYACONFIG)/etc/SASSecurityCertificateFramework/tokens/consul/default/client.token";
+ infile "%mf_loc(VIYACONFIG)&tokloc/client.token";
input token:$64.;
call symputx('consul_token',token);
run;
@@ -97,8 +101,9 @@ run;
/* request the client details */
%let fname1=%mf_getuniquefileref();
proc http method='POST' out=&fname1
- url="&base_uri/SASLogon/oauth/clients/consul?callback=false%str(&)serviceId=app";
- headers "X-Consul-Token"="&consul_token";
+ url="&base_uri/SASLogon/oauth/clients/consul?callback=false%str(&)%trim(
+ )serviceId=app";
+ headers "X-Consul-Token"="&consul_token";
run;
%let libref=%mf_getuniquelibref();
@@ -111,8 +116,8 @@ data _null_;
run;
/**
- * register the new client
- */
+ * register the new client
+ */
%let fname2=%mf_getuniquefileref();
%if x&client_id.x=xx %then %do;
%let client_id=client_%sysfunc(ranuni(0),hex16.);
@@ -122,7 +127,8 @@ run;
%let scopes=%sysfunc(coalescec(&scopes,openid));
%let scopes=%mf_getquotedstr(&scopes,QUOTE=D,indlm=|);
%let grant_type=%mf_getquotedstr(&grant_type,QUOTE=D,indlm=|);
-%let required_user_groups=%mf_getquotedstr(&required_user_groups,QUOTE=D,indlm=|);
+%let required_user_groups=
+ %mf_getquotedstr(&required_user_groups,QUOTE=D,indlm=|);
data _null_;
file &fname2;
@@ -139,9 +145,11 @@ data _null_;
if reqd_groups = '""' then reqd_groups ='';
else reqd_groups=cats(',"required_user_groups":[',reqd_groups,']');
autoapprove=trim(symget('autoapprove'));
- if not missing(autoapprove) then autoapprove=cats(',"autoapprove":',autoapprove);
+ if not missing(autoapprove) then autoapprove=
+ cats(',"autoapprove":',autoapprove);
use_session=trim(symget('use_session'));
- if not missing(use_session) then use_session=cats(',"use_session":',use_session);
+ if not missing(use_session) then use_session=
+ cats(',"use_session":',use_session);
put '{' clientid ;
put clientsecret ;
@@ -206,10 +214,12 @@ run;
%put GRANT_TYPE=&grant_type;
%put;
%if %index(%superq(grant_type),authorization_code) %then %do;
- /* cannot use base_uri here as it includes the protocol which may be incorrect externally */
- %put NOTE: The developer must also register below and select 'openid' to get the grant code:;
+ /* cannot use base_uri here as it includes the protocol which may be incorrect
+ externally */
+ %put NOTE: Visit the link below and select 'openid' to get the grant code:;
%put NOTE- ;
- %put NOTE- &url/SASLogon/oauth/authorize?client_id=&client_id%str(&)response_type=code;
+ %put NOTE- &url/SASLogon/oauth/authorize?client_id=&client_id%str(&)%trim(
+ )response_type=code;
%put NOTE- ;
%end;
diff --git a/viya/mv_tokenauth.sas b/viya/mv_tokenauth.sas
index 4263683..47c2d58 100644
--- a/viya/mv_tokenauth.sas
+++ b/viya/mv_tokenauth.sas
@@ -15,7 +15,8 @@
Usage:
- filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
+ filename mc url
+ "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc;
@@ -31,13 +32,15 @@
@param outds= A dataset containing access_token and refresh_token
@param client_id= The client name
@param client_secret= client secret
- @param grant_type= valid values are "password" or "authorization_code" (unquoted).
- The default is authorization_code.
- @param code= If grant_type=authorization_code then provide the necessary code here
+ @param grant_type= valid values are "password" or "authorization_code"
+ (unquoted). The default is authorization_code.
+ @param code= If grant_type=authorization_code then provide the necessary code
+ here
@param user= If grant_type=password then provide the username here
@param pass= If grant_type=password then provide the password here
@param access_token_var= The global macro variable to contain the access token
- @param refresh_token_var= The global macro variable to contain the refresh token
+ @param refresh_token_var= The global macro variable to contain the refresh
+ token
@param base_uri= The Viya API server location
@version VIYA V.03.04
@@ -88,7 +91,8 @@
,msg=%str(Authorization code required)
)
-%mp_abort(iftrue=(&grant_type=password and (%str(&user)=%str() or %str(&pass)=%str()))
+%mp_abort(iftrue=(
+ &grant_type=password and (%str(&user)=%str() or %str(&pass)=%str()))
,mac=&sysmacroname
,msg=%str(username / password required)
)
@@ -99,7 +103,7 @@
data _null_;
file &fref1;
if "&grant_type"='authorization_code' then string=cats(
- 'grant_type=authorization_code&code=',symget('code'));
+ 'grant_type=authorization_code&code=',symget('code'));
else string=cats('grant_type=password&username=',symget('user')
,'&password=',symget(pass));
call symputx('grantstring',cats("'",string,"'"));
@@ -107,8 +111,8 @@ run;
/*data _null_;infile &fref1;input;put _infile_;run;*/
/**
- * Request access token
- */
+ * Request access token
+ */
%if &base_uri=#NOTSET# %then %let base_uri=%mf_getplatform(VIYARESTAPI);
%let fref2=%mf_getuniquefileref();
@@ -123,8 +127,8 @@ run;
/*data _null_;infile &fref2;input;put _infile_;run;*/
/**
- * Extract access / refresh tokens
- */
+ * Extract access / refresh tokens
+ */
%let libref=%mf_getuniquelibref();
libname &libref JSON fileref=&fref2;
diff --git a/viya/mv_tokenrefresh.sas b/viya/mv_tokenrefresh.sas
index a3504bd..24977b7 100644
--- a/viya/mv_tokenrefresh.sas
+++ b/viya/mv_tokenrefresh.sas
@@ -32,12 +32,13 @@
@param outds= A dataset containing access_token and refresh_token
@param client_id= The client name (alternative to inds)
@param client_secret= client secret (alternative to inds)
- @param grant_type= valid values are "password" or "authorization_code" (unquoted).
- The default is authorization_code.
+ @param grant_type= valid values are "password" or "authorization_code"
+ (unquoted). The default is authorization_code.
@param user= If grant_type=password then provide the username here
@param pass= If grant_type=password then provide the password here
@param access_token_var= The global macro variable to contain the access token
- @param refresh_token_var= The global macro variable containing the refresh token
+ @param refresh_token_var= The global macro variable containing the refresh
+ token
@version VIYA V.03.04
@author Allan Bowe, source: https://github.com/sasjs/core
@@ -72,7 +73,8 @@ options noquotelenmax;
,msg=%str(Invalid value for grant_type: &grant_type)
)
-%mp_abort(iftrue=(&grant_type=password and (%str(&user)=%str() or %str(&pass)=%str()))
+%mp_abort(
+ iftrue=(&grant_type=password and (%str(&user)=%str() or %str(&pass)=%str()))
,mac=&sysmacroname
,msg=%str(username / password required)
)
@@ -92,8 +94,8 @@ options noquotelenmax;
)
/**
- * Request access token
- */
+ * Request access token
+ */
%local base_uri; /* location of rest apis */
%let base_uri=%mf_getplatform(VIYARESTAPI);
@@ -111,8 +113,8 @@ run;
/*data _null_;infile &fref1;input;put _infile_;run;*/
/**
- * Extract access / refresh tokens
- */
+ * Extract access / refresh tokens
+ */
%let libref=%mf_getuniquelibref();
libname &libref JSON fileref=&fref1;
diff --git a/viya/mv_webout.sas b/viya/mv_webout.sas
index c02d1bb..44f965b 100644
--- a/viya/mv_webout.sas
+++ b/viya/mv_webout.sas
@@ -109,7 +109,8 @@
if _n_=1 then call symputx('input_statement',_infile_);
list;
data &table;
- infile "%sysfunc(pathname(work))/&table..csv" firstobs=2 dsd termstr=crlf;
+ infile "%sysfunc(pathname(work))/&table..csv" firstobs=2 dsd
+ termstr=crlf;
input &input_statement;
run;
%end;
@@ -141,7 +142,7 @@
/* setup webout */
OPTIONS NOBOMFILE;
%if "X&SYS_JES_JOB_URI.X"="XX" %then %do;
- filename _webout temp lrecl=999999 mod;
+ filename _webout temp lrecl=999999 mod;
%end;
%else %do;
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI"
@@ -150,7 +151,8 @@
/* setup temp ref */
%if %upcase(&fref) ne _WEBOUT %then %do;
- filename &fref temp lrecl=999999 permission='A::u::rwx,A::g::rw-,A::o::---' mod;
+ filename &fref temp lrecl=999999 permission='A::u::rwx,A::g::rw-,A::o::---'
+ mod;
%end;
/* setup json */