Files
dc/sas/sasjs/macros/mpe_columnlevelsecurity.sas
T
Mihajlo Medjedovic f268de21a3
Test / Build-and-test-development (push) Failing after 6m14s
Test / Build-and-test-development-latest-adapter (push) Failing after 6m13s
init
2023-07-13 13:44:05 +02:00

142 lines
3.8 KiB
SAS

/**
@file
@brief Filters a table with CLS rules
@details Implements CLS as per the rules described here:
https://docs.datacontroller.io/column-level-security/
Usage:
%mpe_columnlevelsecurity(TGTLIB,TGTDS,work.inds
,mode=VIEW
,clsds=dc.mpe_cls
,groupds=work.groups
,outds=work.final
,outmeta=work.cls_rules
)
@param [in] tgtlib The libref of the target table
@param [in] tgtds The dataset reference of the target table
@param [in] inds A two-level (lib.ds) reference to the WORK table to which to
apply the column filter rules
@param [in] mode= (VIEW) Either VIEW or EDIT to indicate whether the
resulting table is intended to be viewable or editable.
@param [in] groupds= (work.groups)A two-level (lib.ds) reference to a dataset
containing the list of groups of which the current user is a member. The
column containing the group name should be called `groupname`.
@param [in] clsds= (work.clsds) A two-level (lib.ds) reference to the
configuration table containing the CLS rules to apply.
@param [out] outds= (WORK.CLSVIEW) A two-level (lib.ds) reference to the WORK
dataset to create
@param [out] outmeta= (WORK.CLS_RULES)The rule metadata, with the following
structure:
|CLS_VARIABLE_NM:$32.|CLS_HIDE:best.|
|---|---|---|---|---|
|`SOME_VARIABLE`|`0 `|
|`VAR3`|`1 `|
<h4> SAS Macros </h4>
@author 4GL Apps Ltd
@copyright 4GL Apps Ltd. This code may only be used within Data Controller
and may not be re-distributed or re-sold without the express permission of
4GL Apps Ltd.
**/
%macro mpe_columnlevelsecurity(tgtlib,tgtds,inds
,mode=VIEW
,groupds=work.groups
,clsds=work.clsview
,outds=CLSVIEW
,outmeta=work.cls_rules
);
%local col_list is_admin;
/* filter for the appropriate rules */
proc sql;
create table &outmeta as
select CLS_VARIABLE_NM,
min(case when CLS_HIDE=1 then 1 else 0 end) as CLS_HIDE
from &clsds
where &dc_dttmtfmt. lt tx_to
and CLS_SCOPE in ("&mode",'ALL')
and CLS_ACTIVE=1
%if &mode=VIEW %then %do;
and CLS_HIDE ne 1
%end;
and upcase(CLS_GROUP) in (select upcase(groupname) from &groupds)
and CLS_LIBREF="%upcase(&tgtlib)"
and CLS_TABLE="%upcase(&tgtds)"
group by CLS_VARIABLE_NM;
%let is_admin=0;
proc sql;
select count(*) into: is_admin from &groupds where groupname="&MPEADMINS";
%put &sysmacroname: &=is_admin;
%if %mf_nobs(work.cls_rules) = 0 or &is_admin>0 %then %do;
%put &sysmacroname: no CLS rules to apply;
%put &=is_admin;
/* copy using append for speed */
data &outds;
set &inds;
stop;
run;
proc append base=&outds data=&inds;
run;
/* ensure CLS_RULES is empty in case of admin */
data &outmeta;
set &outmeta;
stop;
run;
%return;
%end;
%else %if &mode=VIEW %then %do;
/* just send back the relevant columns */
%let col_list=0;
proc sql noprint;
select CLS_VARIABLE_NM into: col_list separated by ' ' from &outmeta
where CLS_HIDE=0;
%if &col_list=0 %then %do;
/*
We have columns that are set to CLS_HIDE=1 but we do not have any to
explicitly show. Therefore we assume all columns are to be shown except
those that are explicitly hidden.
*/
proc sql noprint;
select CLS_VARIABLE_NM into: col_list separated by ' ' from &outmeta
where CLS_HIDE=1;
data &outds;
set &inds;
drop &col_list;
run;
%end;
%else %do;
data &outds;
set &inds;
keep &col_list;
run;
%end;
%end;
%else %if &mode=EDIT %then %do;
/*
In this case we pass all columns and the frontend will filter out the
ones that are not allowed to be edited.
*/
data &outds;
set &inds;
stop;
run;
proc append base=&outds data=&inds;
run;
%end;
%else %do;
%put &sysmacroname: invalid mode - &mode!;
%abort;
%end;
%mend mpe_columnlevelsecurity;