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

Compare commits

...

44 Commits

Author SHA1 Message Date
Allan Bowe
b72e404d52 Merge pull request #264 from sasjs/allanbowe/add-sysencoding-to-webout-263
feat: adding sysencoding to SASJS and SAS9 server types
2022-06-25 15:16:13 +02:00
Allan Bowe
e31cdeef42 feat: adding sysencoding to SASJS and SAS9 server types
Not added for mv_webout (viya) as that is always UTF-8.  Closes #263
2022-06-25 13:11:14 +00:00
Allan Bowe
8a4e32cc27 chore: updating sasjsconfig 2022-06-21 21:33:33 +00:00
Allan Bowe
f285505b79 Merge pull request #262 from sasjs/allanbowe/mp-ds-cards-does-not-261
fix: special missing support in mp_ds2cards()
2022-06-21 19:37:51 +02:00
Allan Bowe
67f5c50300 fix: special missing support in mp_ds2cards() 2022-06-21 17:34:44 +00:00
Yury Shkoda
ce39e4f779 Merge pull request #260 from sasjs/pr-template
chore(template): added pull request template
2022-06-21 19:57:11 +03:00
Yury Shkoda
9c80f5664c chore(template): added pull request template 2022-06-21 19:51:23 +03:00
Allan Bowe
83466c001b Merge pull request #259 from sasjs/allanbowe/mp-jsonout-not-escaping-258
fix: escaping labels in mp_jsonout when showmeta=YES.  Closes #258
2022-06-21 16:16:07 +02:00
Allan Bowe
ad315be503 fix: escaping labels in mp_jsonout when showmeta=YES. Closes #258 2022-06-21 14:14:35 +00:00
Allan Bowe
c41ae2dcc8 fix: enabling sasjsprocessmode as global var in mp_abort
Also, reduced indentation
2022-06-18 13:11:35 +00:00
d9f8e92fac Merge pull request #257 from sasjs/userfeat
feat: filter mm_getusers on a particular user
2022-06-17 19:59:38 +02:00
Allan Bowe
d42ede15db fix: superq 2022-06-17 17:58:39 +00:00
Allan Bowe
08ea9f7c00 chore: all.sas 2022-06-17 17:55:28 +00:00
Allan Bowe
c327e1fc0d fix: apostrophes 2022-06-17 17:55:01 +00:00
Allan Bowe
02fddcf9a1 fix: removing pipes 2022-06-17 17:51:36 +00:00
Allan Bowe
4752bfbb05 fix: refactor xml 2022-06-17 17:47:34 +00:00
Allan Bowe
767ddd7add feat: filter mm_getusers on a particular user
This can be useful for extracting the uri of a metadata user
2022-06-17 17:03:25 +00:00
Allan Bowe
54a24ced83 fix: using sasjs username in mf_getuser() 2022-06-17 15:54:30 +00:00
Allan Bowe
57ae2981f1 Merge pull request #256 from sasjs/allanbowe/mp-abort-fails-on-windows-254
fix: superq() for sysprocessname
2022-06-17 15:29:22 +02:00
Allan Bowe
a3043ac685 fix: superq() for sysprocessname 2022-06-17 13:28:51 +00:00
Allan Bowe
2bdb90b0be Merge pull request #255 from sasjs/allanbowe/mp-abort-fails-on-windows-254
fix: handling embedded speechmarks in SYSPROCESSNAME.  Closes #254
2022-06-17 14:32:02 +02:00
Allan Bowe
2cd846d504 fix: handling embedded speechmarks in SYSPROCESSNAME. Closes #254 2022-06-17 12:30:40 +00:00
Allan Bowe
f593c7bec9 fix: returning user list (single user) in desktop mode in ms_getusers() 2022-06-17 07:52:39 +00:00
Allan Bowe
c8805db0b5 feat: filter for groups by user id in ms_getgroups 2022-06-17 07:46:51 +00:00
Allan Bowe
1eb6d8cec9 feat: enabling user list by group id as well as name 2022-06-17 07:16:57 +00:00
Allan Bowe
ed19ee03af Merge pull request #253 from sasjs/servergroups
feat: enabling group macros on sasjs/server
2022-06-16 13:40:36 +02:00
Allan Bowe
a1c931b5e6 fix: tests with new APIs are now passing 2022-06-16 11:37:31 +00:00
Allan Bowe
cb553a31ab fix: failing test for filtering groups for a particular user (api isn't ready yet) 2022-06-14 19:37:06 +00:00
Allan Bowe
557df272ff fix: using new user/by/username api in sasjs/server 2022-06-14 19:24:41 +00:00
Allan Bowe
0cb3c96c15 feat: enabling group macros on sasjs/server
This PR updates ms_getgroups with a user filter, and ms_getusers with a group filter. ms_adduser2group was also created to faciliate the necessary test(s).
2022-06-14 13:40:05 +00:00
Allan Bowe
1cb39d4d61 Merge pull request #252 from sasjs/allanbowe/ms-getgroups-fails-in-251
fix: creating empty table in desktop mode (ms_getgroups)
2022-06-11 21:30:03 +02:00
Allan Bowe
934b7d4f8a fix: creating empty table in desktop mode (ms_getgroups) 2022-06-11 19:29:21 +00:00
Allan Bowe
24c50cde56 fix: use options nobomfile for sasjs server mp_abort, also doc update in mf_existvarlist 2022-06-09 22:16:34 +00:00
Allan Bowe
055e8d2f13 fix: setting header in mp_abort for sasjs server 2022-06-07 14:01:54 +00:00
Allan Bowe
abfe7fe339 fix: no json wrapper in SASjs mode in mp_abort.sas 2022-06-07 11:28:59 +00:00
Allan Bowe
16ed91f6a9 fix: mp_abort on windows m6+ 2022-06-06 11:28:37 +00:00
Allan Bowe
67ba2a5286 fix: mp_abort on m6 win needs endsas 2022-06-03 17:45:27 +00:00
Allan Bowe
3d7f9b71e1 fix: hard abort in mm_getstpcode when the stp does not exist 2022-06-02 17:50:50 +00:00
Allan Bowe
1d972fad11 fix: using outref instead of outloc in mm_getstpcode invocation from mx_getcode 2022-05-31 22:42:40 +00:00
Allan Bowe
e23bc461c4 fix: mx_getcode platform support 2022-05-31 22:00:58 +00:00
Allan Bowe
28ed458b83 Merge pull request #250 from sasjs/allanbowe/mp-jsonout-needs-to-support-249
fix: enable reserved names in mp_jsonout.  Closes #249
2022-05-31 16:48:45 +03:00
Allan Bowe
827210e010 fix: enable reserved names in mp_jsonout. Closes #249 2022-05-31 13:48:09 +00:00
Allan Bowe
de2f32da36 Merge pull request #248 from sasjs/mm_createdataset_update
fix: cater for case of zero cols in mm_createdataset.sas
2022-05-31 14:02:13 +03:00
Allan Bowe
6fa0fc5dc6 fix: cater for case of zero cols in mm_createdataset.sas 2022-05-31 11:01:06 +00:00
30 changed files with 1309 additions and 609 deletions

17
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,17 @@
## Issue
Link any related issue(s) in this section.
## Intent
What this PR intends to achieve.
## Implementation
What code changes have been made to achieve the intent.
## Checks
- [ ] Code is formatted correctly (`sasjs lint`).
- [ ] Any new functionality has been unit tested.
- [ ] All unit tests are passing (`sasjs test`).

481
all.sas
View File

@@ -324,9 +324,6 @@ https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md#functionex
%put %mf_existVarList(sashelp.class, age sex name dummyvar);
<h4> SAS Macros </h4>
@li mf_abort.sas
@param libds 2 part dataset or view reference
@param varlist space separated variable names
@@ -1144,18 +1141,19 @@ or %index(&pgm,/tests/testteardown)
@author Allan Bowe
**/
%macro mf_getuser(type=META
%macro mf_getuser(
)/*/STORE SOURCE*/;
%local user metavar;
%if &type=OS %then %let metavar=_secureusername;
%else %let metavar=_metaperson;
%local user;
%if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER;
%else %if %symexist(&metavar) %then %do;
%if %length(&&&metavar)=0 %then %let user=&sysuserid;
%if %symexist(_sasjs_username) %then %let user=&_sasjs_username;
%else %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %do;
%let user=&SYS_COMPUTE_SESSION_OWNER;
%end;
%else %if %symexist(_metaperson) %then %do;
%if %length(&_metaperson)=0 %then %let user=&sysuserid;
/* sometimes SAS will add @domain extension - remove for consistency */
/* but be sure to quote in case of usernames with commas */
%else %let user=%unquote(%scan(%quote(&&&metavar),1,@));
%else %let user=%unquote(%scan(%quote(&_metaperson),1,@));
%end;
%else %let user=&sysuserid;
@@ -2200,16 +2198,20 @@ Usage:
recognise this and fetch the log of the parent session instead)
@li STP environments must finish cleanly to avoid the log being sent to
_webout. To assist with this, we also run stpsrvset('program error', 0)
and set SYSCC=0. We take a unique "soft abort" approach - we open a macro
and set SYSCC=0.
Where possible, we take a unique "soft abort" approach - we open a macro
but don't close it! This works everywhere EXCEPT inside a \%include inside
a macro. For that, we recommend you use mp_include.sas to perform the
include, and then call \%mp_abort(mode=INCLUDE) from the source program (ie,
OUTSIDE of the top-parent macro).
The soft abort has also been found to be ineffective in 9.4m6 windows
environments and above, so in these cases, endsas is used.
@param mac= to contain the name of the calling macro
@param mac= (mp_abort.sas) To contain the name of the calling macro. Do not
use &sysmacroname as this will always resolve to MP_ABORT.
@param msg= message to be returned
@param iftrue= supply a condition under which the macro should be executed.
@param iftrue= (1=1) Supply a condition for which the macro should be executed
@param errds= (work.mp_abort_errds) There is no clean way to end a process
within a %include called within a macro. Furthermore, there is no way to
test if a macro is called within a %include. To handle this particular
@@ -2230,11 +2232,12 @@ Usage:
@li REGULAR (default)
@li INCLUDE
@version 9.4
@author Allan Bowe
<h4> Related Macros </h4>
@li mp_include.sas
@version 9.4
@author Allan Bowe
@cond
**/
@@ -2243,7 +2246,8 @@ Usage:
, mode=REGULAR
)/*/STORE SOURCE*/;
%global sysprocessmode sysprocessname;
%global sysprocessmode sysprocessname sasjs_stpsrv_header_loc sasjsprocessmode;
%local fref fid i;
%if not(%eval(%unquote(&iftrue))) %then %return;
@@ -2253,7 +2257,7 @@ Usage:
%if %symexist(_SYSINCLUDEFILEDEVICE)
/* abort cancel FILE does not restart outside the INCLUDE on Viya 3.5 */
and "&SYSPROCESSNAME " ne "Compute Server "
and %superq(SYSPROCESSNAME) ne %str(Compute Server)
%then %do;
%if "*&_SYSINCLUDEFILEDEVICE*" ne "**" %then %do;
data &errds;
@@ -2271,7 +2275,7 @@ Usage:
/* Web App Context */
%if %symexist(_PROGRAM)
or "&SYSPROCESSNAME "="Compute Server "
or %superq(SYSPROCESSNAME) = %str(Compute Server)
or &mode=INCLUDE
%then %do;
options obs=max replace mprint;
@@ -2337,8 +2341,8 @@ Usage:
%end;
%if %symexist(SYS_JES_JOB_URI) %then %do;
/* setup webout */
OPTIONS NOBOMFILE;
/* setup webout for Viya */
options nobomfile;
%if "X&SYS_JES_JOB_URI.X"="XX" %then %do;
filename _webout temp lrecl=999999 mod;
%end;
@@ -2347,11 +2351,24 @@ Usage:
name="_webout.json" lrecl=999999 mod;
%end;
%end;
%else %if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc))=0 %then %do;
options nobomfile;
/* set up http header for SASjs Server */
%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(Content-Type: application/json)));
%let rc=%sysfunc(fwrite(&fid));
%let rc=%sysfunc(fclose(&fid));
%let rc=%sysfunc(filename(&fref));
%end;
/* send response in SASjs JSON format */
data _null_;
file _webout mod lrecl=32000 encoding='utf-8';
length msg syswarningtext syserrortext $32767 ;
length msg syswarningtext syserrortext $32767 mode $10 ;
sasdatetime=datetime();
msg=symget('msg');
%if &logline>0 %then %do;
@@ -2367,7 +2384,8 @@ Usage:
msg=cats('"',msg,'"');
if symexist('_debug') then debug=quote(trim(symget('_debug')));
else debug='""';
put '>>weboutBEGIN<<';
if symget('sasjsprocessmode')='Stored Program' then mode='SASJS';
if mode ne 'SASJS' then put '>>weboutBEGIN<<';
put '{"SYSDATE" : "' "&SYSDATE" '"';
put ',"SYSTIME" : "' "&SYSTIME" '"';
put ',"sasjsAbort" : [{';
@@ -2399,8 +2417,8 @@ Usage:
syswarningtext=quote(trim(symget('syswarningtext')));
put ",""SYSWARNINGTEXT"" : " syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
put "}" @;
put '>>weboutEND<<';
put "}" ;
if mode ne 'SASJS' then put '>>weboutEND<<';
run;
%put _all_;
@@ -2411,6 +2429,13 @@ Usage:
rc=stpsrvset('program error', 0);
call symputx("syscc",0,"g");
run;
%if &sysscp=WIN
and "%substr(%str(&sysvlong ),1,8)"="9.04.01M"
and "%substr(%str(&sysvlong ),9,1)">"5" %then %do;
/* skip approach (below) does not work in windows m6+ envs */
endsas;
%end;
%else %do;
/**
* endsas kills 9.4m3 deployments by orphaning multibridges.
* Abort variants are ungraceful (non zero return code)
@@ -2428,6 +2453,7 @@ Usage:
run;
%inc skip;
%end;
%end;
%else %if "&sysprocessmode " = "SAS Compute Server " %then %do;
/* endsas kills the session making it harder to fetch results */
data _null_;
@@ -4777,7 +4803,7 @@ drop table &out_ds;
@cond
**/
%macro mp_ds2cards(base_ds=, tgt_ds=
%macro mp_ds2cards(base_ds, tgt_ds=
,cards_file="%sysfunc(pathname(work))/cardgen.sas"
,maxobs=max
,random_sample=NO
@@ -4980,6 +5006,7 @@ data _null_;
;
%end;
put ";";
put 'missing a b c d e f g h i j k l m n o p q r s t u v w x y z _;';
put "datalines4;";
end;
end;
@@ -8787,7 +8814,7 @@ options
%do i=1 %to &numcols;
%if &i>1 %then "," ;
%if &action=OBJ %then """&&name&i"":" ;
&&name&i
"&&name&i"n /* name literal for reserved variable names */
%end;
%if &action=ARR %then "]" ; %else "}" ; ;
/* now write the long strings to _webout 1 byte at a time */
@@ -8819,7 +8846,7 @@ options
do i=1 to &numcols;
name=quote(trim(symget(cats('name',i))));
format=quote(trim(symget(cats('fmt',i))));
label=quote(trim(symget(cats('label',i))));
label=quote(prxchange('s/\\/\\\\/',-1,trim(symget(cats('label',i)))));
length=quote(trim(symget(cats('length',i))));
type=quote(trim(symget(cats('typelong',i))));
if i>1 then put "," @@;
@@ -12992,6 +13019,9 @@ create table &libds(
@details Adds a user to a metadata group. The macro first checks whether the
user is in that group, and if not, the user is added.
Note that the macro does not check inherited group memberships - it looks at
direct members only.
Usage:
%mm_adduser2group(user=sasdemo
@@ -13000,10 +13030,10 @@ create table &libds(
@param user= the user name (not displayname)
@param group= the group to which to add the user
@param mdebug= set to 1 to show debug info in log
@param mdebug= (0) set to 1 to show debug info in log
@warning the macro does not check inherited group memberships - it looks at
direct members only
<h4> Related Files </h4>
@li ms_adduser2group.sas
@version 9.3
@author Allan Bowe
@@ -13801,18 +13831,17 @@ run;
%mend mm_createapplication;/**
@file mm_createdataset.sas
@brief Create a dataset from a metadata definition
@file
@brief Create an empty dataset from a metadata definition
@details This macro was built to support viewing empty tables in
https://datacontroller.io - a free evaluation copy is available by
contacting the author (Allan Bowe).
https://datacontroller.io
The table can be retrieved using LIBRARY.DATASET reference, or directly
using the metadata URI.
The dataset is written to the WORK library.
usage:
Usage:
%mm_createdataset(libds=metlib.some_dataset)
@@ -13828,9 +13857,9 @@ run;
@param libds= library.dataset metadata source. Note - table names in metadata
can be longer than 32 chars (just fyi, not an issue here)
@param tableuri= Metadata URI of the table to be created
@param outds= The dataset to create, default is `work.mm_createdataset`.
The table name needs to be 32 chars or less as per SAS naming rules.
@param mdebug= set DBG to 1 to disable DEBUG messages
@param outds= (work.mm_createdataset) The dataset to create. The table name
needs to be 32 chars or less as per SAS naming rules.
@param mdebug= (0) Set to 1 to enable DEBUG messages
@version 9.4
@author Allan Bowe
@@ -13856,14 +13885,23 @@ run;
%mm_gettables(uri=&liburi,outds=&tempds2)
data _null_;
set &tempds2;
if upcase(tablename)="%upcase(%scan(&libds,2,.))";
where upcase(tablename)="%upcase(%scan(&libds,2,.))";
&dbg putlog tableuri=;
call symputx('tableuri',tableuri);
run;
%end;
data;run;%let tempds3=&syslast;
data;run;
%let tempds3=&syslast;
%mm_getcols(tableuri=&tableuri,outds=&tempds3)
%if %mf_nobs(&tempds3)=0 %then %do;
%put &libds (&tableuri) has no columns defined!!;
data &outds;
run;
%return;
%end;
data _null_;
set &tempds3 end=last;
if _n_=1 then call execute('data &outds;');
@@ -15156,7 +15194,7 @@ data _null_;
put ' %do i=1 %to &numcols; ';
put ' %if &i>1 %then "," ; ';
put ' %if &action=OBJ %then """&&name&i"":" ; ';
put ' &&name&i ';
put ' "&&name&i"n /* name literal for reserved variable names */ ';
put ' %end; ';
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
put ' /* now write the long strings to _webout 1 byte at a time */ ';
@@ -15188,7 +15226,7 @@ data _null_;
put ' do i=1 to &numcols; ';
put ' name=quote(trim(symget(cats(''name'',i)))); ';
put ' format=quote(trim(symget(cats(''fmt'',i)))); ';
put ' label=quote(trim(symget(cats(''label'',i)))); ';
put ' label=quote(prxchange(''s/\\/\\\\/'',-1,trim(symget(cats(''label'',i))))); ';
put ' length=quote(trim(symget(cats(''length'',i)))); ';
put ' type=quote(trim(symget(cats(''typelong'',i)))); ';
put ' if i>1 then put "," @@; ';
@@ -15207,18 +15245,19 @@ data _null_;
put '%end; ';
put '%mend mp_jsonout; ';
put ' ';
put '%macro mf_getuser(type=META ';
put '%macro mf_getuser( ';
put ')/*/STORE SOURCE*/; ';
put ' %local user metavar; ';
put ' %if &type=OS %then %let metavar=_secureusername; ';
put ' %else %let metavar=_metaperson; ';
put ' %local user; ';
put ' ';
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
put ' %else %if %symexist(&metavar) %then %do; ';
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
put ' %if %symexist(_sasjs_username) %then %let user=&_sasjs_username; ';
put ' %else %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %do; ';
put ' %let user=&SYS_COMPUTE_SESSION_OWNER; ';
put ' %end; ';
put ' %else %if %symexist(_metaperson) %then %do; ';
put ' %if %length(&_metaperson)=0 %then %let user=&sysuserid; ';
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
put ' /* but be sure to quote in case of usernames with commas */ ';
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
put ' %else %let user=%unquote(%scan(%quote(&_metaperson),1,@)); ';
put ' %end; ';
put ' %else %let user=&sysuserid; ';
put ' ';
@@ -15343,6 +15382,7 @@ data _null_;
put ' put '',"_METAPERSON": '' _METAPERSON; ';
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
put ' put ",""SYSCC"" : ""&syscc"" "; ';
put ' put ",""SYSENCODING"" : ""&sysencoding"" "; ';
put ' syserrortext=quote(cats(symget(''SYSERRORTEXT''))); ';
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
@@ -16215,8 +16255,6 @@ filename __outdoc clear;
directories
@param [in] mDebug= set to 1 to show debug messages in the log
<h4> SAS Macros </h4>
@version 9.4
@author Allan Bowe
@@ -17155,6 +17193,7 @@ filename __mc2 clear;
<h4> SAS Macros </h4>
@li mf_getuniquefileref.sas
@li mp_abort.sas
@author Allan Bowe
@@ -17204,11 +17243,10 @@ data _null_;
else put (_all_)(=);
run;
%if &tsuri=stopifempty %then %do;
%put %str(WARN)ING: &tree&name.(StoredProcess) not found!;
%return;
%end;
%mp_abort(iftrue= (&tsuri=stopifempty)
,mac=mm_getstpcode
,msg=%str(&tree&name.(StoredProcess) not found!)
)
/**
* Now we can extract the textstore
@@ -17747,17 +17785,18 @@ libname _XML_ clear;
%mm_getusers()
Optionally, filter for a user (useful to get the uri):
%mm_getusers(user=&_metaperson)
@param outds the dataset to create that contains the list of libraries
@returns outds dataset containing all users, with the following columns:
- uri
- name
@warning The following filenames are created and then de-assigned:
filename sxlemap clear;
filename response clear;
libname _XML_ clear;
@param user= (0) Set to a metadata user to filter on that user
@param outds= (work.mm_getusers) The output table to create
@version 9.3
@author Allan Bowe
@@ -17765,10 +17804,12 @@ libname _XML_ clear;
**/
%macro mm_getusers(
outds=work.mm_getusers
outds=work.mm_getusers,
user=0
)/*/STORE SOURCE*/;
filename response temp;
%if %superq(user)=0 %then %do;
proc metadata in= '<GetMetadataObjects>
<Reposid>$METAREPOSITORY</Reposid>
<Type>Person</Type>
@@ -17782,6 +17823,30 @@ proc metadata in= '<GetMetadataObjects>
</GetMetadataObjects>'
out=response;
run;
%end;
%else %do;
filename inref temp;
data _null_;
file inref;
put "<GetMetadataObjects>";
put "<Reposid>$METAREPOSITORY</Reposid>";
put "<Type>Person</Type>";
put "<NS>SAS</NS>";
put "<!-- Specify the OMI_XMLSELECT (128) flag -->";
put "<Flags>128</Flags>";
put "<Options>";
put "<Templates>";
put '<Person Name=""/>';
put "</Templates>";
length string $10000;
string=cats('<XMLSELECT search="Person[@Name=',"'&user'",']"/>');
put string;
put "</Options>";
put "</GetMetadataObjects>";
run;
proc metadata in=inref out=response;
run;
%end;
filename sxlemap temp;
data _null_;
@@ -18863,6 +18928,7 @@ run;
put ',"_METAPERSON": ' _METAPERSON;
put ',"_PROGRAM" : ' _PROGRAM ;
put ",""SYSCC"" : ""&syscc"" ";
put ",""SYSENCODING"" : ""&sysencoding"" ";
syserrortext=quote(cats(symget('SYSERRORTEXT')));
put ',"SYSERRORTEXT" : ' syserrortext;
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
@@ -19070,6 +19136,128 @@ run;
%let rc=%sysfunc(filename(&fref));
%mend mfs_httpheader;
/**
@file
@brief Adds a user to a group on SASjs Server
@details Adds a user to a group based on userid and groupid. Both user and
group must already exist.
Examples:
%ms_adduser2group(uid=1,gid=1)
@param [in] uid= (0) The User ID to be added
@param [in] gid= (0) The Group ID to contain the new user
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
@param [out] outds= (work.ms_adduser2group) This output dataset will contain
the new list of group members, eg:
|DISPLAYNAME:$18.|USERNAME:$10.|ID:best.|
|---|---|---|
|`Super Admin `|`secretuser `|`1`|
|`Sabir Hassan`|`sabir`|`2`|
|`Mihajlo Medjedovic `|`mihajlo `|`3`|
|`Ivor Townsend `|`ivor `|`4`|
|`New User `|`newuser `|`5`|
<h4> SAS Macros </h4>
@li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas
@li mp_abort.sas
<h4> Related Files </h4>
@li ms_creategroup.sas
@li ms_createuser.sas
**/
%macro ms_adduser2group(uid=0
,gid=0
,outds=work.ms_adduser2group
,mdebug=0
);
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_adduser2group.sas
,msg=%str(syscc=&syscc on macro entry)
)
%local fref0 fref1 fref2 libref optval rc msg;
%let fref0=%mf_getuniquefileref();
%let fref1=%mf_getuniquefileref();
%let libref=%mf_getuniquelibref();
/* avoid sending bom marker to API */
%let optval=%sysfunc(getoption(bomfile));
options nobomfile;
data _null_;
file &fref0 lrecl=1000;
infile "&_sasjs_tokenfile" lrecl=1000;
input;
if _n_=1 then put "accept: application/json";
put _infile_;
run;
%if &mdebug=1 %then %do;
%put _local_;
data _null_;
infile &fref0;
input;
put _infile_;
run;
%end;
proc http method='POST' headerin=&fref0 out=&fref1
url="&_sasjs_apiserverurl/SASjsApi/group/&gid/&uid";
%if &mdebug=1 %then %do;
debug level=1;
%end;
run;
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_adduser2group.sas
,msg=%str(Issue submitting query to SASjsApi/group)
)
libname &libref JSON fileref=&fref1;
data &outds;
set &libref..users;
drop ordinal_root ordinal_users;
%if &mdebug=1 %then %do;
putlog _all_;
%end;
run;
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_creategroup.sas
,msg=%str(Issue reading response JSON)
)
/* reset options */
options &optval;
%if &mdebug=0 %then %do;
filename &fref0 clear;
filename &fref1 clear;
libname &libref clear;
%end;
%else %do;
data _null_;
infile &fref1;
input;
putlog _infile_;
run;
%end;
%mend ms_adduser2group;
/**
@file
@brief Creates a file on SASjs Drive
@@ -19745,7 +19933,7 @@ data _null_;
put ' %do i=1 %to &numcols; ';
put ' %if &i>1 %then "," ; ';
put ' %if &action=OBJ %then """&&name&i"":" ; ';
put ' &&name&i ';
put ' "&&name&i"n /* name literal for reserved variable names */ ';
put ' %end; ';
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
put ' /* now write the long strings to _webout 1 byte at a time */ ';
@@ -19777,7 +19965,7 @@ data _null_;
put ' do i=1 to &numcols; ';
put ' name=quote(trim(symget(cats(''name'',i)))); ';
put ' format=quote(trim(symget(cats(''fmt'',i)))); ';
put ' label=quote(trim(symget(cats(''label'',i)))); ';
put ' label=quote(prxchange(''s/\\/\\\\/'',-1,trim(symget(cats(''label'',i))))); ';
put ' length=quote(trim(symget(cats(''length'',i)))); ';
put ' type=quote(trim(symget(cats(''typelong'',i)))); ';
put ' if i>1 then put "," @@; ';
@@ -19796,18 +19984,19 @@ data _null_;
put '%end; ';
put '%mend mp_jsonout; ';
put ' ';
put '%macro mf_getuser(type=META ';
put '%macro mf_getuser( ';
put ')/*/STORE SOURCE*/; ';
put ' %local user metavar; ';
put ' %if &type=OS %then %let metavar=_secureusername; ';
put ' %else %let metavar=_metaperson; ';
put ' %local user; ';
put ' ';
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
put ' %else %if %symexist(&metavar) %then %do; ';
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
put ' %if %symexist(_sasjs_username) %then %let user=&_sasjs_username; ';
put ' %else %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %do; ';
put ' %let user=&SYS_COMPUTE_SESSION_OWNER; ';
put ' %end; ';
put ' %else %if %symexist(_metaperson) %then %do; ';
put ' %if %length(&_metaperson)=0 %then %let user=&sysuserid; ';
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
put ' /* but be sure to quote in case of usernames with commas */ ';
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
put ' %else %let user=%unquote(%scan(%quote(&_metaperson),1,@)); ';
put ' %end; ';
put ' %else %let user=&sysuserid; ';
put ' ';
@@ -19922,6 +20111,7 @@ data _null_;
put ' put ",""_DEBUG"" : ""&_debug"" "; ';
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
put ' put ",""SYSCC"" : ""&syscc"" "; ';
put ' put ",""SYSENCODING"" : ""&sysencoding"" "; ';
put ' syserrortext=quote(cats(symget(''SYSERRORTEXT''))); ';
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
put ' SYSHOSTINFOLONG=quote(trim(symget(''SYSHOSTINFOLONG''))); ';
@@ -20115,13 +20305,24 @@ filename &headref clear;
@file
@brief Fetches the list of groups from SASjs Server
@details Fetches the list of groups from SASjs Server and writes them to an
output dataset.
output dataset. Provide a username to filter for the groups for a particular
user.
Example:
%ms_getgroups(outds=userlist)
With filter on username:
%ms_getgroups(outds=userlist, user=James)
With filter on userid:
%ms_getgroups(outds=userlist, uid=1)
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
@param [in] user= (0) Provide the username on which to filter
@param [in] uid= (0) Provide the userid on which to filter
@param [out] outds= (work.ms_getgroups) This output dataset will contain the
list of groups. Format:
|NAME:$32.|DESCRIPTION:$64.|GROUPID:best.|
@@ -20138,22 +20339,38 @@ filename &headref clear;
<h4> Related Files </h4>
@li ms_creategroup.sas
@li ms_getusers.test.sas
@li ms_getgroups.test.sas
**/
%macro ms_getgroups(
outds=work.ms_getgroups
,mdebug=0
user=0,
uid=0,
outds=work.ms_getgroups,
mdebug=0
);
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_getusers.sas
,mac=ms_getgroups.sas
,msg=%str(syscc=&syscc on macro entry)
)
%local fref0 fref1 libref optval rc msg;
%local fref0 fref1 libref optval rc msg url;
%if %sysget(MODE)=desktop %then %do;
/* groups api does not exist in desktop mode */
data &outds;
length NAME $32 DESCRIPTION $64. GROUPID 8;
name="&sysuserid";
description="&sysuserid (group - desktop mode)";
groupid=1;
output;
stop;
run;
%return;
%end;
%let fref0=%mf_getuniquefileref();
%let fref1=%mf_getuniquefileref();
%let libref=%mf_getuniquelibref();
@@ -20178,8 +20395,13 @@ run;
run;
%end;
%if "&user" ne "0" %then %let url=/SASjsApi/user/by/username/&user;
%else %if "&uid" ne "0" %then %let url=/SASjsApi/user/&uid;
%else %let url=/SASjsApi/group;
proc http method='GET' headerin=&fref0 out=&fref1
url="&_sasjs_apiserverurl/SASjsApi/group";
url="&_sasjs_apiserverurl.&url";
%if &mdebug=1 %then %do;
debug level=1;
%end;
@@ -20188,21 +20410,31 @@ run;
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_getgroups.sas
,msg=%str(Issue submitting GET query to SASjsApi/group)
,msg=%str(Issue submitting GET query to SASjsApi)
)
libname &libref JSON fileref=&fref1;
%if "&user"="0" and "&uid"="0" %then %do;
data &outds;
length NAME $32 DESCRIPTION $64. GROUPID 8;
if _n_=1 then call missing(of _all_);
set &libref..root;
drop ordinal_root;
run;
%end;
%else %do;
data &outds;
length NAME $32 DESCRIPTION $64. GROUPID 8;
if _n_=1 then call missing(of _all_);
set &libref..groups;
drop ordinal_:;
run;
%end;
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_getusers.sas
,mac=ms_getgroups.sas
,msg=%str(Issue reading response JSON)
)
@@ -20220,16 +20452,26 @@ options &optval;
@file
@brief Fetches the list of users from SASjs Server
@details Fetches the list of users from SASjs Server and writes them to an
output dataset.
output dataset. Can also be filtered, for a particular group.
Example:
%ms_getusers(outds=userlist)
Filtering for a group by group name:
%ms_getusers(outds=work.groupmembers, group=GROUPNAME)
Filtering for a group by group id:
%ms_getusers(outds=work.groupmembers, gid=1)
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
@param [in] group= (0) Set to a group name to filter members for that group
@param [in] gid= (0) Set to a group id to filter members for that group
@param [out] outds= (work.ms_getusers) This output dataset will contain the
list of user accounts. Format:
|DISPLAYNAME:$18.|USERNAME:$10.|ID:best.|
|DISPLAYNAME:$60.|USERNAME:$30.|ID:best.|
|---|---|---|
|`Super Admin `|`secretuser `|`1`|
|`Sabir Hassan`|`sabir`|`2`|
@@ -20238,7 +20480,6 @@ options &optval;
|`New User `|`newuser `|`5`|
<h4> SAS Macros </h4>
@li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas
@@ -20246,13 +20487,16 @@ options &optval;
<h4> Related Files </h4>
@li ms_createuser.sas
@li ms_getgroups.sas
@li ms_getusers.test.sas
**/
%macro ms_getusers(
outds=work.ms_getusers
,mdebug=0
outds=work.ms_getusers,
group=0,
gid=0,
mdebug=0
);
%mp_abort(
@@ -20261,11 +20505,24 @@ options &optval;
,msg=%str(syscc=&syscc on macro entry)
)
%local fref0 fref1 libref optval rc msg;
%local fref0 fref1 libref optval rc msg url;
%let fref0=%mf_getuniquefileref();
%let fref1=%mf_getuniquefileref();
%let libref=%mf_getuniquelibref();
%if %sysget(MODE)=desktop %then %do;
/* users api does not exist in desktop mode */
data &outds;
length DISPLAYNAME $60 USERNAME:$30 ID 8;
USERNAME="&sysuserid";
DISPLAYNAME="&sysuserid (desktop mode)";
ID=1;
output;
stop;
run;
%return;
%end;
/* avoid sending bom marker to API */
%let optval=%sysfunc(getoption(bomfile));
options nobomfile;
@@ -20286,26 +20543,40 @@ run;
run;
%end;
%if "&group" ne "0" %then %let url=/SASjsApi/group/by/groupname/&group;
%else %if "&gid" ne "0" %then %let url=/SASjsApi/group/&gid;
%else %let url=/SASjsApi/user;
proc http method='GET' headerin=&fref0 out=&fref1
url="&_sasjs_apiserverurl/SASjsApi/user";
url="&_sasjs_apiserverurl.&url";
%if &mdebug=1 %then %do;
debug level=1;
%end;
run;
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_getusers.sas
,msg=%str(Issue submitting GET query to SASjsApi/user)
,msg=%str(Issue submitting API query)
)
libname &libref JSON fileref=&fref1;
%if "&group"="0" and "&gid"="0" %then %do;
data &outds;
length DISPLAYNAME $60 USERNAME:$30 ID 8;
set &libref..root;
drop ordinal_root;
run;
%end;
%else %do;
data &outds;
length DISPLAYNAME $60 USERNAME:$30 ID 8;
set &libref..users;
drop ordinal_root ordinal_users;
run;
%end;
%mp_abort(
iftrue=(&syscc ne 0)
@@ -20830,6 +21101,7 @@ run;
put ",""_DEBUG"" : ""&_debug"" ";
put ',"_PROGRAM" : ' _PROGRAM ;
put ",""SYSCC"" : ""&syscc"" ";
put ",""SYSENCODING"" : ""&sysencoding"" ";
syserrortext=quote(cats(symget('SYSERRORTEXT')));
put ',"SYSERRORTEXT" : ' syserrortext;
SYSHOSTINFOLONG=quote(trim(symget('SYSHOSTINFOLONG')));
@@ -22006,7 +22278,7 @@ data _null_;
put ' %do i=1 %to &numcols; ';
put ' %if &i>1 %then "," ; ';
put ' %if &action=OBJ %then """&&name&i"":" ; ';
put ' &&name&i ';
put ' "&&name&i"n /* name literal for reserved variable names */ ';
put ' %end; ';
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
put ' /* now write the long strings to _webout 1 byte at a time */ ';
@@ -22038,7 +22310,7 @@ data _null_;
put ' do i=1 to &numcols; ';
put ' name=quote(trim(symget(cats(''name'',i)))); ';
put ' format=quote(trim(symget(cats(''fmt'',i)))); ';
put ' label=quote(trim(symget(cats(''label'',i)))); ';
put ' label=quote(prxchange(''s/\\/\\\\/'',-1,trim(symget(cats(''label'',i))))); ';
put ' length=quote(trim(symget(cats(''length'',i)))); ';
put ' type=quote(trim(symget(cats(''typelong'',i)))); ';
put ' if i>1 then put "," @@; ';
@@ -22057,18 +22329,19 @@ data _null_;
put '%end; ';
put '%mend mp_jsonout; ';
put ' ';
put '%macro mf_getuser(type=META ';
put '%macro mf_getuser( ';
put ')/*/STORE SOURCE*/; ';
put ' %local user metavar; ';
put ' %if &type=OS %then %let metavar=_secureusername; ';
put ' %else %let metavar=_metaperson; ';
put ' %local user; ';
put ' ';
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
put ' %else %if %symexist(&metavar) %then %do; ';
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
put ' %if %symexist(_sasjs_username) %then %let user=&_sasjs_username; ';
put ' %else %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %do; ';
put ' %let user=&SYS_COMPUTE_SESSION_OWNER; ';
put ' %end; ';
put ' %else %if %symexist(_metaperson) %then %do; ';
put ' %if %length(&_metaperson)=0 %then %let user=&sysuserid; ';
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
put ' /* but be sure to quote in case of usernames with commas */ ';
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
put ' %else %let user=%unquote(%scan(%quote(&_metaperson),1,@)); ';
put ' %end; ';
put ' %else %let user=&sysuserid; ';
put ' ';
@@ -26971,8 +27244,8 @@ Usage:
%if &platform=SASJS %then %do;
%ms_getfile(&loc..sas, outref=&outref)
%end;
%else %if &platform=SAS9 %then %do;
%mm_getstpcode(tree=&loc,outloc=&outref)
%else %if &platform=SAS9 or &platform=SASMETA %then %do;
%mm_getstpcode(tree=&loc,outref=&outref)
%end;
%else %if &platform=SASVIYA %then %do;
/* extract name & path from &loc */

View File

@@ -6,9 +6,6 @@
%put %mf_existVarList(sashelp.class, age sex name dummyvar);
<h4> SAS Macros </h4>
@li mf_abort.sas
@param libds 2 part dataset or view reference
@param varlist space separated variable names

View File

@@ -23,18 +23,19 @@
@author Allan Bowe
**/
%macro mf_getuser(type=META
%macro mf_getuser(
)/*/STORE SOURCE*/;
%local user metavar;
%if &type=OS %then %let metavar=_secureusername;
%else %let metavar=_metaperson;
%local user;
%if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER;
%else %if %symexist(&metavar) %then %do;
%if %length(&&&metavar)=0 %then %let user=&sysuserid;
%if %symexist(_sasjs_username) %then %let user=&_sasjs_username;
%else %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %do;
%let user=&SYS_COMPUTE_SESSION_OWNER;
%end;
%else %if %symexist(_metaperson) %then %do;
%if %length(&_metaperson)=0 %then %let user=&sysuserid;
/* sometimes SAS will add @domain extension - remove for consistency */
/* but be sure to quote in case of usernames with commas */
%else %let user=%unquote(%scan(%quote(&&&metavar),1,@));
%else %let user=%unquote(%scan(%quote(&_metaperson),1,@));
%end;
%else %let user=&sysuserid;

View File

@@ -15,16 +15,20 @@
recognise this and fetch the log of the parent session instead)
@li STP environments must finish cleanly to avoid the log being sent to
_webout. To assist with this, we also run stpsrvset('program error', 0)
and set SYSCC=0. We take a unique "soft abort" approach - we open a macro
and set SYSCC=0.
Where possible, we take a unique "soft abort" approach - we open a macro
but don't close it! This works everywhere EXCEPT inside a \%include inside
a macro. For that, we recommend you use mp_include.sas to perform the
include, and then call \%mp_abort(mode=INCLUDE) from the source program (ie,
OUTSIDE of the top-parent macro).
The soft abort has also been found to be ineffective in 9.4m6 windows
environments and above, so in these cases, endsas is used.
@param mac= to contain the name of the calling macro
@param mac= (mp_abort.sas) To contain the name of the calling macro. Do not
use &sysmacroname as this will always resolve to MP_ABORT.
@param msg= message to be returned
@param iftrue= supply a condition under which the macro should be executed.
@param iftrue= (1=1) Supply a condition for which the macro should be executed
@param errds= (work.mp_abort_errds) There is no clean way to end a process
within a %include called within a macro. Furthermore, there is no way to
test if a macro is called within a %include. To handle this particular
@@ -45,11 +49,12 @@
@li REGULAR (default)
@li INCLUDE
@version 9.4
@author Allan Bowe
<h4> Related Macros </h4>
@li mp_include.sas
@version 9.4
@author Allan Bowe
@cond
**/
@@ -58,7 +63,8 @@
, mode=REGULAR
)/*/STORE SOURCE*/;
%global sysprocessmode sysprocessname;
%global sysprocessmode sysprocessname sasjs_stpsrv_header_loc sasjsprocessmode;
%local fref fid i;
%if not(%eval(%unquote(&iftrue))) %then %return;
@@ -68,7 +74,7 @@
%if %symexist(_SYSINCLUDEFILEDEVICE)
/* abort cancel FILE does not restart outside the INCLUDE on Viya 3.5 */
and "&SYSPROCESSNAME " ne "Compute Server "
and %superq(SYSPROCESSNAME) ne %str(Compute Server)
%then %do;
%if "*&_SYSINCLUDEFILEDEVICE*" ne "**" %then %do;
data &errds;
@@ -86,7 +92,7 @@
/* Web App Context */
%if %symexist(_PROGRAM)
or "&SYSPROCESSNAME "="Compute Server "
or %superq(SYSPROCESSNAME) = %str(Compute Server)
or &mode=INCLUDE
%then %do;
options obs=max replace mprint;
@@ -152,8 +158,8 @@
%end;
%if %symexist(SYS_JES_JOB_URI) %then %do;
/* setup webout */
OPTIONS NOBOMFILE;
/* setup webout for Viya */
options nobomfile;
%if "X&SYS_JES_JOB_URI.X"="XX" %then %do;
filename _webout temp lrecl=999999 mod;
%end;
@@ -162,11 +168,24 @@
name="_webout.json" lrecl=999999 mod;
%end;
%end;
%else %if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc))=0 %then %do;
options nobomfile;
/* set up http header for SASjs Server */
%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(Content-Type: application/json)));
%let rc=%sysfunc(fwrite(&fid));
%let rc=%sysfunc(fclose(&fid));
%let rc=%sysfunc(filename(&fref));
%end;
/* send response in SASjs JSON format */
data _null_;
file _webout mod lrecl=32000 encoding='utf-8';
length msg syswarningtext syserrortext $32767 ;
length msg syswarningtext syserrortext $32767 mode $10 ;
sasdatetime=datetime();
msg=symget('msg');
%if &logline>0 %then %do;
@@ -182,7 +201,8 @@
msg=cats('"',msg,'"');
if symexist('_debug') then debug=quote(trim(symget('_debug')));
else debug='""';
put '>>weboutBEGIN<<';
if symget('sasjsprocessmode')='Stored Program' then mode='SASJS';
if mode ne 'SASJS' then put '>>weboutBEGIN<<';
put '{"SYSDATE" : "' "&SYSDATE" '"';
put ',"SYSTIME" : "' "&SYSTIME" '"';
put ',"sasjsAbort" : [{';
@@ -214,8 +234,8 @@
syswarningtext=quote(trim(symget('syswarningtext')));
put ",""SYSWARNINGTEXT"" : " syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
put "}" @;
put '>>weboutEND<<';
put "}" ;
if mode ne 'SASJS' then put '>>weboutEND<<';
run;
%put _all_;
@@ -226,6 +246,13 @@
rc=stpsrvset('program error', 0);
call symputx("syscc",0,"g");
run;
%if &sysscp=WIN
and "%substr(%str(&sysvlong ),1,8)"="9.04.01M"
and "%substr(%str(&sysvlong ),9,1)">"5" %then %do;
/* skip approach (below) does not work in windows m6+ envs */
endsas;
%end;
%else %do;
/**
* endsas kills 9.4m3 deployments by orphaning multibridges.
* Abort variants are ungraceful (non zero return code)
@@ -243,6 +270,7 @@
run;
%inc skip;
%end;
%end;
%else %if "&sysprocessmode " = "SAS Compute Server " %then %do;
/* endsas kills the session making it harder to fetch results */
data _null_;

View File

@@ -51,7 +51,7 @@
@cond
**/
%macro mp_ds2cards(base_ds=, tgt_ds=
%macro mp_ds2cards(base_ds, tgt_ds=
,cards_file="%sysfunc(pathname(work))/cardgen.sas"
,maxobs=max
,random_sample=NO
@@ -254,6 +254,7 @@ data _null_;
;
%end;
put ";";
put 'missing a b c d e f g h i j k l m n o p q r s t u v w x y z _;';
put "datalines4;";
end;
end;

View File

@@ -231,7 +231,7 @@
%do i=1 %to &numcols;
%if &i>1 %then "," ;
%if &action=OBJ %then """&&name&i"":" ;
&&name&i
"&&name&i"n /* name literal for reserved variable names */
%end;
%if &action=ARR %then "]" ; %else "}" ; ;
/* now write the long strings to _webout 1 byte at a time */
@@ -263,7 +263,7 @@
do i=1 to &numcols;
name=quote(trim(symget(cats('name',i))));
format=quote(trim(symget(cats('fmt',i))));
label=quote(trim(symget(cats('label',i))));
label=quote(prxchange('s/\\/\\\\/',-1,trim(symget(cats('label',i)))));
length=quote(trim(symget(cats('length',i))));
type=quote(trim(symget(cats('typelong',i))));
if i>1 then put "," @@;

View File

@@ -4,6 +4,9 @@
@details Adds a user to a metadata group. The macro first checks whether the
user is in that group, and if not, the user is added.
Note that the macro does not check inherited group memberships - it looks at
direct members only.
Usage:
%mm_adduser2group(user=sasdemo
@@ -12,10 +15,10 @@
@param user= the user name (not displayname)
@param group= the group to which to add the user
@param mdebug= set to 1 to show debug info in log
@param mdebug= (0) set to 1 to show debug info in log
@warning the macro does not check inherited group memberships - it looks at
direct members only
<h4> Related Files </h4>
@li ms_adduser2group.sas
@version 9.3
@author Allan Bowe

View File

@@ -1,16 +1,15 @@
/**
@file mm_createdataset.sas
@brief Create a dataset from a metadata definition
@file
@brief Create an empty dataset from a metadata definition
@details This macro was built to support viewing empty tables in
https://datacontroller.io - a free evaluation copy is available by
contacting the author (Allan Bowe).
https://datacontroller.io
The table can be retrieved using LIBRARY.DATASET reference, or directly
using the metadata URI.
The dataset is written to the WORK library.
usage:
Usage:
%mm_createdataset(libds=metlib.some_dataset)
@@ -26,9 +25,9 @@
@param libds= library.dataset metadata source. Note - table names in metadata
can be longer than 32 chars (just fyi, not an issue here)
@param tableuri= Metadata URI of the table to be created
@param outds= The dataset to create, default is `work.mm_createdataset`.
The table name needs to be 32 chars or less as per SAS naming rules.
@param mdebug= set DBG to 1 to disable DEBUG messages
@param outds= (work.mm_createdataset) The dataset to create. The table name
needs to be 32 chars or less as per SAS naming rules.
@param mdebug= (0) Set to 1 to enable DEBUG messages
@version 9.4
@author Allan Bowe
@@ -54,14 +53,23 @@
%mm_gettables(uri=&liburi,outds=&tempds2)
data _null_;
set &tempds2;
if upcase(tablename)="%upcase(%scan(&libds,2,.))";
where upcase(tablename)="%upcase(%scan(&libds,2,.))";
&dbg putlog tableuri=;
call symputx('tableuri',tableuri);
run;
%end;
data;run;%let tempds3=&syslast;
data;run;
%let tempds3=&syslast;
%mm_getcols(tableuri=&tableuri,outds=&tempds3)
%if %mf_nobs(&tempds3)=0 %then %do;
%put &libds (&tableuri) has no columns defined!!;
data &outds;
run;
%return;
%end;
data _null_;
set &tempds3 end=last;
if _n_=1 then call execute('data &outds;');

View File

@@ -264,7 +264,7 @@ data _null_;
put ' %do i=1 %to &numcols; ';
put ' %if &i>1 %then "," ; ';
put ' %if &action=OBJ %then """&&name&i"":" ; ';
put ' &&name&i ';
put ' "&&name&i"n /* name literal for reserved variable names */ ';
put ' %end; ';
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
put ' /* now write the long strings to _webout 1 byte at a time */ ';
@@ -296,7 +296,7 @@ data _null_;
put ' do i=1 to &numcols; ';
put ' name=quote(trim(symget(cats(''name'',i)))); ';
put ' format=quote(trim(symget(cats(''fmt'',i)))); ';
put ' label=quote(trim(symget(cats(''label'',i)))); ';
put ' label=quote(prxchange(''s/\\/\\\\/'',-1,trim(symget(cats(''label'',i))))); ';
put ' length=quote(trim(symget(cats(''length'',i)))); ';
put ' type=quote(trim(symget(cats(''typelong'',i)))); ';
put ' if i>1 then put "," @@; ';
@@ -315,18 +315,19 @@ data _null_;
put '%end; ';
put '%mend mp_jsonout; ';
put ' ';
put '%macro mf_getuser(type=META ';
put '%macro mf_getuser( ';
put ')/*/STORE SOURCE*/; ';
put ' %local user metavar; ';
put ' %if &type=OS %then %let metavar=_secureusername; ';
put ' %else %let metavar=_metaperson; ';
put ' %local user; ';
put ' ';
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
put ' %else %if %symexist(&metavar) %then %do; ';
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
put ' %if %symexist(_sasjs_username) %then %let user=&_sasjs_username; ';
put ' %else %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %do; ';
put ' %let user=&SYS_COMPUTE_SESSION_OWNER; ';
put ' %end; ';
put ' %else %if %symexist(_metaperson) %then %do; ';
put ' %if %length(&_metaperson)=0 %then %let user=&sysuserid; ';
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
put ' /* but be sure to quote in case of usernames with commas */ ';
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
put ' %else %let user=%unquote(%scan(%quote(&_metaperson),1,@)); ';
put ' %end; ';
put ' %else %let user=&sysuserid; ';
put ' ';
@@ -451,6 +452,7 @@ data _null_;
put ' put '',"_METAPERSON": '' _METAPERSON; ';
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
put ' put ",""SYSCC"" : ""&syscc"" "; ';
put ' put ",""SYSENCODING"" : ""&sysencoding"" "; ';
put ' syserrortext=quote(cats(symget(''SYSERRORTEXT''))); ';
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';

View File

@@ -17,8 +17,6 @@
directories
@param [in] mDebug= set to 1 to show debug messages in the log
<h4> SAS Macros </h4>
@version 9.4
@author Allan Bowe

View File

@@ -21,6 +21,7 @@
<h4> SAS Macros </h4>
@li mf_getuniquefileref.sas
@li mp_abort.sas
@author Allan Bowe
@@ -70,11 +71,10 @@ data _null_;
else put (_all_)(=);
run;
%if &tsuri=stopifempty %then %do;
%put %str(WARN)ING: &tree&name.(StoredProcess) not found!;
%return;
%end;
%mp_abort(iftrue= (&tsuri=stopifempty)
,mac=mm_getstpcode
,msg=%str(&tree&name.(StoredProcess) not found!)
)
/**
* Now we can extract the textstore

View File

@@ -8,17 +8,18 @@
%mm_getusers()
Optionally, filter for a user (useful to get the uri):
%mm_getusers(user=&_metaperson)
@param outds the dataset to create that contains the list of libraries
@returns outds dataset containing all users, with the following columns:
- uri
- name
@warning The following filenames are created and then de-assigned:
filename sxlemap clear;
filename response clear;
libname _XML_ clear;
@param user= (0) Set to a metadata user to filter on that user
@param outds= (work.mm_getusers) The output table to create
@version 9.3
@author Allan Bowe
@@ -26,10 +27,12 @@
**/
%macro mm_getusers(
outds=work.mm_getusers
outds=work.mm_getusers,
user=0
)/*/STORE SOURCE*/;
filename response temp;
%if %superq(user)=0 %then %do;
proc metadata in= '<GetMetadataObjects>
<Reposid>$METAREPOSITORY</Reposid>
<Type>Person</Type>
@@ -43,6 +46,30 @@ proc metadata in= '<GetMetadataObjects>
</GetMetadataObjects>'
out=response;
run;
%end;
%else %do;
filename inref temp;
data _null_;
file inref;
put "<GetMetadataObjects>";
put "<Reposid>$METAREPOSITORY</Reposid>";
put "<Type>Person</Type>";
put "<NS>SAS</NS>";
put "<!-- Specify the OMI_XMLSELECT (128) flag -->";
put "<Flags>128</Flags>";
put "<Options>";
put "<Templates>";
put '<Person Name=""/>';
put "</Templates>";
length string $10000;
string=cats('<XMLSELECT search="Person[@Name=',"'&user'",']"/>');
put string;
put "</Options>";
put "</GetMetadataObjects>";
run;
proc metadata in=inref out=response;
run;
%end;
filename sxlemap temp;
data _null_;

View File

@@ -157,6 +157,7 @@
put ',"_METAPERSON": ' _METAPERSON;
put ',"_PROGRAM" : ' _PROGRAM ;
put ",""SYSCC"" : ""&syscc"" ";
put ",""SYSENCODING"" : ""&sysencoding"" ";
syserrortext=quote(cats(symget('SYSERRORTEXT')));
put ',"SYSERRORTEXT" : ' syserrortext;
put ",""SYSHOSTNAME"" : ""&syshostname"" ";

View File

@@ -67,7 +67,6 @@
},
{
"name": "server",
"serverUrl": "https://sas.analytium.co.uk:5007",
"serverType": "SASJS",
"httpsAgentOptions": {
"allowInsecureRequests": false

122
server/ms_adduser2group.sas Normal file
View File

@@ -0,0 +1,122 @@
/**
@file
@brief Adds a user to a group on SASjs Server
@details Adds a user to a group based on userid and groupid. Both user and
group must already exist.
Examples:
%ms_adduser2group(uid=1,gid=1)
@param [in] uid= (0) The User ID to be added
@param [in] gid= (0) The Group ID to contain the new user
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
@param [out] outds= (work.ms_adduser2group) This output dataset will contain
the new list of group members, eg:
|DISPLAYNAME:$18.|USERNAME:$10.|ID:best.|
|---|---|---|
|`Super Admin `|`secretuser `|`1`|
|`Sabir Hassan`|`sabir`|`2`|
|`Mihajlo Medjedovic `|`mihajlo `|`3`|
|`Ivor Townsend `|`ivor `|`4`|
|`New User `|`newuser `|`5`|
<h4> SAS Macros </h4>
@li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas
@li mp_abort.sas
<h4> Related Files </h4>
@li ms_creategroup.sas
@li ms_createuser.sas
**/
%macro ms_adduser2group(uid=0
,gid=0
,outds=work.ms_adduser2group
,mdebug=0
);
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_adduser2group.sas
,msg=%str(syscc=&syscc on macro entry)
)
%local fref0 fref1 fref2 libref optval rc msg;
%let fref0=%mf_getuniquefileref();
%let fref1=%mf_getuniquefileref();
%let libref=%mf_getuniquelibref();
/* avoid sending bom marker to API */
%let optval=%sysfunc(getoption(bomfile));
options nobomfile;
data _null_;
file &fref0 lrecl=1000;
infile "&_sasjs_tokenfile" lrecl=1000;
input;
if _n_=1 then put "accept: application/json";
put _infile_;
run;
%if &mdebug=1 %then %do;
%put _local_;
data _null_;
infile &fref0;
input;
put _infile_;
run;
%end;
proc http method='POST' headerin=&fref0 out=&fref1
url="&_sasjs_apiserverurl/SASjsApi/group/&gid/&uid";
%if &mdebug=1 %then %do;
debug level=1;
%end;
run;
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_adduser2group.sas
,msg=%str(Issue submitting query to SASjsApi/group)
)
libname &libref JSON fileref=&fref1;
data &outds;
set &libref..users;
drop ordinal_root ordinal_users;
%if &mdebug=1 %then %do;
putlog _all_;
%end;
run;
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_creategroup.sas
,msg=%str(Issue reading response JSON)
)
/* reset options */
options &optval;
%if &mdebug=0 %then %do;
filename &fref0 clear;
filename &fref1 clear;
libname &libref clear;
%end;
%else %do;
data _null_;
infile &fref1;
input;
putlog _infile_;
run;
%end;
%mend ms_adduser2group;

View File

@@ -266,7 +266,7 @@ data _null_;
put ' %do i=1 %to &numcols; ';
put ' %if &i>1 %then "," ; ';
put ' %if &action=OBJ %then """&&name&i"":" ; ';
put ' &&name&i ';
put ' "&&name&i"n /* name literal for reserved variable names */ ';
put ' %end; ';
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
put ' /* now write the long strings to _webout 1 byte at a time */ ';
@@ -298,7 +298,7 @@ data _null_;
put ' do i=1 to &numcols; ';
put ' name=quote(trim(symget(cats(''name'',i)))); ';
put ' format=quote(trim(symget(cats(''fmt'',i)))); ';
put ' label=quote(trim(symget(cats(''label'',i)))); ';
put ' label=quote(prxchange(''s/\\/\\\\/'',-1,trim(symget(cats(''label'',i))))); ';
put ' length=quote(trim(symget(cats(''length'',i)))); ';
put ' type=quote(trim(symget(cats(''typelong'',i)))); ';
put ' if i>1 then put "," @@; ';
@@ -317,18 +317,19 @@ data _null_;
put '%end; ';
put '%mend mp_jsonout; ';
put ' ';
put '%macro mf_getuser(type=META ';
put '%macro mf_getuser( ';
put ')/*/STORE SOURCE*/; ';
put ' %local user metavar; ';
put ' %if &type=OS %then %let metavar=_secureusername; ';
put ' %else %let metavar=_metaperson; ';
put ' %local user; ';
put ' ';
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
put ' %else %if %symexist(&metavar) %then %do; ';
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
put ' %if %symexist(_sasjs_username) %then %let user=&_sasjs_username; ';
put ' %else %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %do; ';
put ' %let user=&SYS_COMPUTE_SESSION_OWNER; ';
put ' %end; ';
put ' %else %if %symexist(_metaperson) %then %do; ';
put ' %if %length(&_metaperson)=0 %then %let user=&sysuserid; ';
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
put ' /* but be sure to quote in case of usernames with commas */ ';
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
put ' %else %let user=%unquote(%scan(%quote(&_metaperson),1,@)); ';
put ' %end; ';
put ' %else %let user=&sysuserid; ';
put ' ';
@@ -443,6 +444,7 @@ data _null_;
put ' put ",""_DEBUG"" : ""&_debug"" "; ';
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
put ' put ",""SYSCC"" : ""&syscc"" "; ';
put ' put ",""SYSENCODING"" : ""&sysencoding"" "; ';
put ' syserrortext=quote(cats(symget(''SYSERRORTEXT''))); ';
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
put ' SYSHOSTINFOLONG=quote(trim(symget(''SYSHOSTINFOLONG''))); ';

View File

@@ -2,13 +2,24 @@
@file
@brief Fetches the list of groups from SASjs Server
@details Fetches the list of groups from SASjs Server and writes them to an
output dataset.
output dataset. Provide a username to filter for the groups for a particular
user.
Example:
%ms_getgroups(outds=userlist)
With filter on username:
%ms_getgroups(outds=userlist, user=James)
With filter on userid:
%ms_getgroups(outds=userlist, uid=1)
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
@param [in] user= (0) Provide the username on which to filter
@param [in] uid= (0) Provide the userid on which to filter
@param [out] outds= (work.ms_getgroups) This output dataset will contain the
list of groups. Format:
|NAME:$32.|DESCRIPTION:$64.|GROUPID:best.|
@@ -25,22 +36,38 @@
<h4> Related Files </h4>
@li ms_creategroup.sas
@li ms_getusers.test.sas
@li ms_getgroups.test.sas
**/
%macro ms_getgroups(
outds=work.ms_getgroups
,mdebug=0
user=0,
uid=0,
outds=work.ms_getgroups,
mdebug=0
);
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_getusers.sas
,mac=ms_getgroups.sas
,msg=%str(syscc=&syscc on macro entry)
)
%local fref0 fref1 libref optval rc msg;
%local fref0 fref1 libref optval rc msg url;
%if %sysget(MODE)=desktop %then %do;
/* groups api does not exist in desktop mode */
data &outds;
length NAME $32 DESCRIPTION $64. GROUPID 8;
name="&sysuserid";
description="&sysuserid (group - desktop mode)";
groupid=1;
output;
stop;
run;
%return;
%end;
%let fref0=%mf_getuniquefileref();
%let fref1=%mf_getuniquefileref();
%let libref=%mf_getuniquelibref();
@@ -65,8 +92,13 @@ run;
run;
%end;
%if "&user" ne "0" %then %let url=/SASjsApi/user/by/username/&user;
%else %if "&uid" ne "0" %then %let url=/SASjsApi/user/&uid;
%else %let url=/SASjsApi/group;
proc http method='GET' headerin=&fref0 out=&fref1
url="&_sasjs_apiserverurl/SASjsApi/group";
url="&_sasjs_apiserverurl.&url";
%if &mdebug=1 %then %do;
debug level=1;
%end;
@@ -75,21 +107,31 @@ run;
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_getgroups.sas
,msg=%str(Issue submitting GET query to SASjsApi/group)
,msg=%str(Issue submitting GET query to SASjsApi)
)
libname &libref JSON fileref=&fref1;
%if "&user"="0" and "&uid"="0" %then %do;
data &outds;
length NAME $32 DESCRIPTION $64. GROUPID 8;
if _n_=1 then call missing(of _all_);
set &libref..root;
drop ordinal_root;
run;
%end;
%else %do;
data &outds;
length NAME $32 DESCRIPTION $64. GROUPID 8;
if _n_=1 then call missing(of _all_);
set &libref..groups;
drop ordinal_:;
run;
%end;
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_getusers.sas
,mac=ms_getgroups.sas
,msg=%str(Issue reading response JSON)
)

View File

@@ -2,16 +2,26 @@
@file
@brief Fetches the list of users from SASjs Server
@details Fetches the list of users from SASjs Server and writes them to an
output dataset.
output dataset. Can also be filtered, for a particular group.
Example:
%ms_getusers(outds=userlist)
Filtering for a group by group name:
%ms_getusers(outds=work.groupmembers, group=GROUPNAME)
Filtering for a group by group id:
%ms_getusers(outds=work.groupmembers, gid=1)
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
@param [in] group= (0) Set to a group name to filter members for that group
@param [in] gid= (0) Set to a group id to filter members for that group
@param [out] outds= (work.ms_getusers) This output dataset will contain the
list of user accounts. Format:
|DISPLAYNAME:$18.|USERNAME:$10.|ID:best.|
|DISPLAYNAME:$60.|USERNAME:$30.|ID:best.|
|---|---|---|
|`Super Admin `|`secretuser `|`1`|
|`Sabir Hassan`|`sabir`|`2`|
@@ -20,7 +30,6 @@
|`New User `|`newuser `|`5`|
<h4> SAS Macros </h4>
@li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas
@@ -28,13 +37,16 @@
<h4> Related Files </h4>
@li ms_createuser.sas
@li ms_getgroups.sas
@li ms_getusers.test.sas
**/
%macro ms_getusers(
outds=work.ms_getusers
,mdebug=0
outds=work.ms_getusers,
group=0,
gid=0,
mdebug=0
);
%mp_abort(
@@ -43,11 +55,24 @@
,msg=%str(syscc=&syscc on macro entry)
)
%local fref0 fref1 libref optval rc msg;
%local fref0 fref1 libref optval rc msg url;
%let fref0=%mf_getuniquefileref();
%let fref1=%mf_getuniquefileref();
%let libref=%mf_getuniquelibref();
%if %sysget(MODE)=desktop %then %do;
/* users api does not exist in desktop mode */
data &outds;
length DISPLAYNAME $60 USERNAME:$30 ID 8;
USERNAME="&sysuserid";
DISPLAYNAME="&sysuserid (desktop mode)";
ID=1;
output;
stop;
run;
%return;
%end;
/* avoid sending bom marker to API */
%let optval=%sysfunc(getoption(bomfile));
options nobomfile;
@@ -68,26 +93,40 @@ run;
run;
%end;
%if "&group" ne "0" %then %let url=/SASjsApi/group/by/groupname/&group;
%else %if "&gid" ne "0" %then %let url=/SASjsApi/group/&gid;
%else %let url=/SASjsApi/user;
proc http method='GET' headerin=&fref0 out=&fref1
url="&_sasjs_apiserverurl/SASjsApi/user";
url="&_sasjs_apiserverurl.&url";
%if &mdebug=1 %then %do;
debug level=1;
%end;
run;
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_getusers.sas
,msg=%str(Issue submitting GET query to SASjsApi/user)
,msg=%str(Issue submitting API query)
)
libname &libref JSON fileref=&fref1;
%if "&group"="0" and "&gid"="0" %then %do;
data &outds;
length DISPLAYNAME $60 USERNAME:$30 ID 8;
set &libref..root;
drop ordinal_root;
run;
%end;
%else %do;
data &outds;
length DISPLAYNAME $60 USERNAME:$30 ID 8;
set &libref..users;
drop ordinal_root ordinal_users;
run;
%end;
%mp_abort(
iftrue=(&syscc ne 0)

View File

@@ -153,6 +153,7 @@
put ",""_DEBUG"" : ""&_debug"" ";
put ',"_PROGRAM" : ' _PROGRAM ;
put ",""SYSCC"" : ""&syscc"" ";
put ",""SYSENCODING"" : ""&sysencoding"" ";
syserrortext=quote(cats(symget('SYSERRORTEXT')));
put ',"SYSERRORTEXT" : ' syserrortext;
SYSHOSTINFOLONG=quote(trim(symget('SYSHOSTINFOLONG')));

View File

@@ -0,0 +1,52 @@
/**
@file
@brief Testing ms_adduser2group.sas macro
<h4> SAS Macros </h4>
@li mf_getuniquename.sas
@li mp_assert.sas
@li mp_assertscope.sas
@li ms_adduser2group.sas
@li ms_creategroup.sas
**/
/* first, create an empty group */
%let group=%substr(%mf_getuniquename(),1,8);
%ms_creategroup(&group, desc=The description,mdebug=&sasjs_mdebug,outds=test1a)
%let groupid=0;
data _null_;
set work.test1a;
call symputx('groupid',groupid);
run;
%mp_assert(
iftrue=(&groupid>0),
desc=Checking that group was created with an ID,
outds=work.test_results
)
/* now add a user (user 1 always exists) */
%mp_assertscope(SNAPSHOT)
%ms_adduser2group(uid=1,gid=&groupid,mdebug=&sasjs_mdebug,outds=test1)
%mp_assertscope(COMPARE
,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN
)
/* check the user is in the output list */
%let checkid=0;
data _null_;
set work.test1;
if id=1 then call symputx('checkid',1);
run;
%mp_assert(
iftrue=(&checkid=1),
desc=Checking that user was created in the new group,
outds=work.test_results
)

View File

@@ -35,7 +35,7 @@ run;
%let checkid=0;
data _null_;
set work.test2;
where name="&group";
where upcase(name)="%upcase(&group)";
call symputx('checkid',groupid);
run;
%mp_assert(

View File

@@ -23,6 +23,7 @@
data _null_;
set work.test1;
call symputx('id',id);
putlog (_all_)(=);
run;
%mp_assert(
iftrue=(&id>0),
@@ -35,7 +36,8 @@ run;
%let checkid=0;
data _null_;
set work.test2;
where username="&user";
if _n_<20 then putlog (_all_)(=);
if upcase(username)="%upcase(&user)";
call symputx('checkid',id);
run;
%mp_assert(

View File

@@ -3,21 +3,64 @@
@brief Testing ms_getgroups.sas macro
<h4> SAS Macros </h4>
@li mf_getuniquename.sas
@li ms_adduser2group.sas
@li ms_creategroup.sas
@li ms_getgroups.sas
@li mp_assert.sas
@li mp_assertdsobs.sas
@li mp_assertscope.sas
**/
/* create a group */
%let group=%substr(%mf_getuniquename(),1,8);
%ms_creategroup(&group, desc=The description,mdebug=&sasjs_mdebug,outds=test1)
/* get groups */
%mp_assertscope(SNAPSHOT)
%ms_getgroups(outds=work.test1,mdebug=&sasjs_mdebug)
%mp_assertscope(COMPARE
,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN
)
/* check the group was created */
%mp_assertdsobs(work.test1,test=ATLEAST 1)
%let test2=0;
%put &=group;
data _null_;
set work.test1;
putlog (_all_)(=);
if upcase(name)="%upcase(&group)" then do;
putlog "&group found!";
call symputx('test2',1);
call symputx('gid',groupid); /* used in next test */
end;
run;
%mp_assert(
iftrue=("&test2"="1"),
desc=Checking group was created,
outds=work.test_results
)
/* now check if the filter for the groups for a user works */
/* add a member */
%ms_adduser2group(uid=1,gid=&gid)
%ms_getgroups(user=secretuser,outds=work.test3)
%let test3=0;
data _null_;
set work.test3;
if groupid=&gid then call symputx('test3',1);
run;
%mp_assert(
iftrue=("&test3"="1"),
desc=Checking group list was returned for a user,
outds=work.test_results
)

View File

@@ -3,6 +3,8 @@
@brief Testing ms_getusers.sas macro
<h4> SAS Macros </h4>
@li ms_creategroup.sas
@li ms_adduser2group.sas
@li ms_getusers.sas
@li mp_assertdsobs.sas
@li mp_assertscope.sas
@@ -18,6 +20,39 @@
%mp_assertdsobs(work.test1,test=ATLEAST 1)
/**
* test the extraction of group members
*/
/* create a group */
%let group=%substr(%mf_getuniquename(),1,8);
%ms_creategroup(&group, desc=some desc,mdebug=&sasjs_mdebug,outds=work.group)
%let gid=0;
data _null_;
set work.group;
call symputx('gid',groupid);
run;
/* add a member */
%ms_adduser2group(uid=1,gid=&gid)
/* extract the members */
%ms_getusers(group=&group,outds=test2)
/* check the user is in the output list */
%let checkid=0;
data _null_;
set work.test2;
if id=1 then call symputx('checkid',1);
run;
%mp_assert(
iftrue=(&checkid=1),
desc=Checking that admin user was created in the new group,
outds=work.test_results
)

View File

@@ -34,7 +34,7 @@ options mprint;
)
%mp_assertscope(COMPARE)
libname webeen json (weboot);
libname webeen json fileref=weboot;
data _null_;
infile weboot;

View File

@@ -10,7 +10,12 @@
**/
filename ft15f001 temp;
parmcards4;
data _null_;
file ft15f001;
infile cards;
input;
put _infile_;
cards4;
%put Initialising sendObj: ;
%put _all_;
%webout(FETCH)
@@ -27,6 +32,7 @@ parmcards4;
%mend x; %x()
%webout(CLOSE)
;;;;
run;
%put creating web service: &mcTestAppLoc/services;
%ms_createwebservice(
path=&mcTestAppLoc/services,

View File

@@ -20,7 +20,7 @@ run;
%ms_webout(OBJ,datasets,fref=&fref)
%ms_webout(CLOSE,fref=&fref)
libname test JSON (&fref);
libname test JSON fileref=&fref;
data root;
set test.root;
call symputx('checkval',sysvlong);

View File

@@ -408,7 +408,7 @@ data _null_;
put ' %do i=1 %to &numcols; ';
put ' %if &i>1 %then "," ; ';
put ' %if &action=OBJ %then """&&name&i"":" ; ';
put ' &&name&i ';
put ' "&&name&i"n /* name literal for reserved variable names */ ';
put ' %end; ';
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
put ' /* now write the long strings to _webout 1 byte at a time */ ';
@@ -440,7 +440,7 @@ data _null_;
put ' do i=1 to &numcols; ';
put ' name=quote(trim(symget(cats(''name'',i)))); ';
put ' format=quote(trim(symget(cats(''fmt'',i)))); ';
put ' label=quote(trim(symget(cats(''label'',i)))); ';
put ' label=quote(prxchange(''s/\\/\\\\/'',-1,trim(symget(cats(''label'',i))))); ';
put ' length=quote(trim(symget(cats(''length'',i)))); ';
put ' type=quote(trim(symget(cats(''typelong'',i)))); ';
put ' if i>1 then put "," @@; ';
@@ -459,18 +459,19 @@ data _null_;
put '%end; ';
put '%mend mp_jsonout; ';
put ' ';
put '%macro mf_getuser(type=META ';
put '%macro mf_getuser( ';
put ')/*/STORE SOURCE*/; ';
put ' %local user metavar; ';
put ' %if &type=OS %then %let metavar=_secureusername; ';
put ' %else %let metavar=_metaperson; ';
put ' %local user; ';
put ' ';
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
put ' %else %if %symexist(&metavar) %then %do; ';
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
put ' %if %symexist(_sasjs_username) %then %let user=&_sasjs_username; ';
put ' %else %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %do; ';
put ' %let user=&SYS_COMPUTE_SESSION_OWNER; ';
put ' %end; ';
put ' %else %if %symexist(_metaperson) %then %do; ';
put ' %if %length(&_metaperson)=0 %then %let user=&sysuserid; ';
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
put ' /* but be sure to quote in case of usernames with commas */ ';
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
put ' %else %let user=%unquote(%scan(%quote(&_metaperson),1,@)); ';
put ' %end; ';
put ' %else %let user=&sysuserid; ';
put ' ';

View File

@@ -34,8 +34,8 @@
%if &platform=SASJS %then %do;
%ms_getfile(&loc..sas, outref=&outref)
%end;
%else %if &platform=SAS9 %then %do;
%mm_getstpcode(tree=&loc,outloc=&outref)
%else %if &platform=SAS9 or &platform=SASMETA %then %do;
%mm_getstpcode(tree=&loc,outref=&outref)
%end;
%else %if &platform=SASVIYA %then %do;
/* extract name & path from &loc */