diff --git a/sas/sasjs/services/public/getchangeinfo.sas b/sas/sasjs/services/public/getchangeinfo.sas index 63a47eb..c65249d 100644 --- a/sas/sasjs/services/public/getchangeinfo.sas +++ b/sas/sasjs/services/public/getchangeinfo.sas @@ -4,9 +4,26 @@ @details

SAS Macros

- @li mf_getengine.sas @li dc_assignlib.sas + @li mf_getengine.sas + @li mf_getuser.sas + @li mf_nobs.sas @li mp_abort.sas + @li mpe_accesscheck.sas + @li mpe_getgroups.sas + +

Service Inputs

+
sascontroltable
+ @li table table ID or LOAD_REF used to uniquely identify a staged change + +

Service Outputs

+ +
work.jsparams
+ Mainly sourced from MPE_SUBMIT plus some extra cols: + + @li LIB_ENGINE Library engine + @li allow_restore YES if a user can restore, else NO + @li REASON reason why a restore is / is no possible @version 9.2 @author 4GL Apps Ltd @@ -35,13 +52,106 @@ data APPROVE1; TABLE_NM=cats(base_lib,'.',base_ds); BASE_TABLE=table_nm; call symputx('base_lib',base_lib); + call symputx('base_ds',base_ds); REVIEWED_ON_DTTM=put(reviewed_on,datetime19.); SUBMITTED_ON_DTTM=put(submitted_on,datetime19.); run; -data jsParams; +/** + * Check if user has basic access permission to RESTORE the table + */ +%put checking access; + +%global allow_restore reason; +%let allow_restore=NO; +%let reason=NOTFOUND; + +%macro access_check(); + + /* grab user groups */ + %let user=%mf_getuser(); + %mpe_getgroups(user=&user,outds=work.groups) + + /* check if user is admin */ + %let is_admin=0; + proc sql; + select count(*) into: is_admin from work.groups where groupname="&MPEADMINS"; + + %if &is_admin>0 %then %do; + %let allow_restore=YES; + %let reason=IS ADMIN; + %return; + %end; + + /* check if user has basic access */ + %mpe_accesscheck(&base_lib..&base_ds,outds=work.access_check + ,user=&user + ,access_level=EDIT + ) + %if %mf_nobs(access_check)=0 %then %do; + %let allow_restore=NO; + %let reason=No access in MPE_TABLES; + %return; + %end; + + /* check if user has column level security rules */ + proc sql; + create table work.cls_rules as + select * + from &mpelib..mpe_column_level_security + where &dc_dttmtfmt. lt tx_to + and CLS_SCOPE in ("EDIT",'ALL') + and CLS_ACTIVE=1 + and upcase(CLS_GROUP) in (select upcase(groupname) from work.groups) + and CLS_LIBREF="%upcase(&base_lib)" + and CLS_TABLE="%upcase(&base_ds)"; + %if %mf_nobs(work.cls_rules)>0 %then %do; + %let allow_restore=NO; + %let reason=User has restrictions in MPE_COLUMN_LEVEL_SECURITY; + data _null_; + set work.cls_rules; + putlog (_all_)(=); + if _n_>5 then stop; + run; + %return; + %end; + + /* check if user has row level security rules */ + proc sql; + create table work.rls_rules as + select * + from &mpelib..mpe_row_level_security + where &dc_dttmtfmt. lt tx_to + and rls_scope in ("EDIT",'ALL') + and upcase(rls_group) in (select upcase(groupname) from work.groups) + and rls_libref="&base_lib" + and rls_table="&base_ds" + and rls_active=1; + %if %mf_nobs(work.rls_rules)>0 %then %do; + %let allow_restore=NO; + %let reason=User has restrictions in MPE_ROW_LEVEL_SECURITY; + data _null_; + set work.rls_rules; + putlog (_all_)(=); + if _n_>5 then stop; + run; + %return; + %end; + %else %do; + %let allow_restore=YES; + %let reason=CHECKS PASSED; + %return; + %end; +%mend access_check; + +%access_check(); + + +data work.jsParams; set approve1; LIB_ENGINE="%mf_getEngine(&base_lib)"; + allow_restore="&allow_restore"; + REASON="&reason"; run; %mp_abort(iftrue= (&syscc ne 0) diff --git a/sas/sasjs/services/public/getchangeinfo.test.sas b/sas/sasjs/services/public/getchangeinfo.test.sas new file mode 100644 index 0000000..8c5625e --- /dev/null +++ b/sas/sasjs/services/public/getchangeinfo.test.sas @@ -0,0 +1,97 @@ +/** + @file + @brief testing getchangeinfo service + +

SAS Macros

+ @li mp_assertcolvals.sas + @li mf_getuniquefileref.sas + +**/ + +%let _program=&appLoc/services/public/getchangeinfo; + +/** + * First part - stage some data (for diffing) + */ +data work.sascontroltable; + action='LOAD'; + message="getdiffs prep"; + libds="&dclib..MPE_X_TEST"; + output; + stop; +run; +proc sql noprint; +select max(primary_key_field) into: maxpk from &dclib..mpe_x_test; +data work.jsdata; + set &dclib..mpe_x_test(rename=( + some_date=dt2 SOME_DATETIME=dttm2 SOME_TIME=tm2) + ); + /* for now, the adapter sends these as strings */ + some_date=put(dt2,date9.); + SOME_DATETIME=put(dttm2,datetime19.); + some_time=put(tm2,time.); + drop dt2 dttm2 tm2; + _____DELETE__THIS__RECORD_____='No'; + if _n_=1 then do; + primary_key_field=sum(&maxpk,1); + some_char=' leadingblanks'; + some_num=._; + output; + end; + else if _n_<3 then do; + SOME_NUM=ranuni(0); + end; + else stop; +run; + +%mx_testservice(&appLoc/services/editors/stagedata, + viyacontext=&defaultcontext, + inputdatasets=work.jsdata work.sascontroltable, + outlib=web1, + mdebug=&sasjs_mdebug +) + +%let status=0; +data work.sasparams; + set web1.sasparams; + putlog (_all_)(=); + if status='SUCCESS' then call symputx('status',1); + call symputx('dsid',dsid); +run; +%mp_assert( + iftrue=(&status=1 and &syscc=0), + desc=Checking successful submission +) + + +/* now call getchangeinfo */ +%let f3=%mf_getuniquefileref(); +data _null_; + file &f3 termstr=crlf; + put 'TABLE:$43.'; + put "&dsid"; +run; +%mp_testservice(&_program, + viyacontext=&defaultcontext, + inputfiles=&f3:sascontroltable, + outlib=web3, + mdebug=&sasjs_mdebug +) + +data work.jsparams; + set web3.jsparams; + putlog (_all_)(=); + call symputx('ALLOW_RESTORE',ALLOW_RESTORE); +run; +%mp_assert( + iftrue=(&syscc=0), + desc=Checking successful execution +) +%mp_assert( + iftrue=(%mf_nobs(work.jsparams)=1), + desc=Checking data was returned +) +%mp_assert( + iftrue=(&allow_edit=YES), + desc=Checking admin user can restore +)