Loading...
Searching...
No Matches
mpe_accesscheck.sas
Go to the documentation of this file.
1/**
2 @file
3 @brief Checks group access level for a table or library
4 @details In order for a user to be able to EDIT or APPROVE a table they must
5 be in a group that has been granted access to that table in the
6 MPE_SECURITY table. Alternatively, they may be in the &mpeadmins
7 group (which has full access to everything).
8
9 @param [in] base_table The base table to check for
10 @param [in] user= The user for which the access level should be returned. If
11 not provided, the mf_user() result is used instead.
12 @param [in] access_level= (APPROVE) access_level (per MPE_SECURITY) reqd.
13 Valid values:
14 @li EDIT
15 @li APPROVE
16 @li VIEW
17 @param [in] cntl_lib_var= (MPELIB) The name of a global macro variable that
18 contains the libref in which the MPE_SECURITY table is stored
19 @param [out] outds= (MED_ACCESSCHECK) Output WORK table containing all the
20 groups for which the user is granted the particular ACCESS_LEVEL.
21
22 <h4> SAS Macros </h4>
23 @li mp_abort.sas
24 @li mf_getuniquename.sas
25 @li mf_getuser.sas
26 @li mpe_validatecol.sas
27 @li mpe_getgroups.sas
28
29 <h4> Related Macros </h4>
30 @li mpe_accesscheck.test.sas
31
32 @version 9.2
33 @author 4GL Apps Ltd
34 @copyright 4GL Apps Ltd. This code may only be used within Data Controller
35 and may not be re-distributed or re-sold without the express permission of
36 4GL Apps Ltd.
37**/
38
39%macro mpe_accesscheck(
40 base_table
41 ,outds=med_accesscheck /* WORK table to contain access details */
42 ,user= /* metadata user to check for */
43 ,access_level=APPROVE
44 ,cntl_lib_var=MPELIB
45 );
46
47 %if &user= %then %let user=%mf_getuser();
48
49 %mp_abort(
50 iftrue=(%index(&outds,.)>0 and %upcase(%scan(&outds,1,.)) ne WORK)
51 ,mac=mpe_accesscheck
52 ,msg=%str(outds should be a WORK table)
53 )
54
55 /**
56 * Validate inputs before they reach executable code. base_table is
57 * interpolated into a SQL where clause (and callers may pass raw request
58 * input), so it must be a well-formed LIBREF.DATASET (or the
59 * LIBREF.CATALOGNAME-FC form of a format catalog) and access_level must
60 * be one of the known levels - anything else aborts before the query is
61 * built. Values are read with symget (never re-resolved) and scanned in
62 * a data step so no macro content in the input can execute.
63 */
64 %local is_libds is_level;
65 %let is_libds=0;
66 %let is_level=0;
67 data _null_;
68 length _bt $64 _lvl $16;
69 _bt=symget('base_table');
70 _lvl=upcase(symget('access_level'));
71 %mpe_validatecol(_bt,LIBDS,is_libds)
72 if is_libds=0 then do;
73 call symputx('is_libds',0,'l');
74 putlog 'ERR' 'OR: Invalid base_table:' _bt;
75 stop;
76 end;
77 if _lvl not in ('EDIT','APPROVE','VIEW','SIGNOFF','AUDIT') then do;
78 call symputx('is_level',0,'l');
79 putlog 'ERR' 'OR: Invalid access_level:' _lvl;
80 stop;
81 end;
82 /* escape any embedded quotes so the value cannot break out of the
83 * double-quoted SQL literals below (defence in depth - the LIBDS
84 * check above already rejects quotes) */
85 _bt=tranwrd(_bt,'"','');
86 call symputx('base_table',_bt,'l');
87 call symputx('access_level',_lvl,'l');
88 call symputx('is_libds',is_libds,'l');
89 call symputx('is_level',1,'l');
90 run;
91
92 %mp_abort(
93 iftrue=(&is_libds ne 1)
94 ,mac=mpe_accesscheck
95 ,msg=%str(Invalid base_table)
96 )
97 %mp_abort(
98 iftrue=(&is_level ne 1)
99 ,mac=mpe_accesscheck
100 ,msg=%str(Invalid access_level)
101 )
102
103 /* make unique temp table vars */
104 %local tempds1 tempds2;
105 %let tempds1=%mf_getuniquename(prefix=usergroups);
106 %let tempds2=%mf_getuniquename(prefix=tablegroups);
107
108 /* get list of user groups */
109 %mpe_getgroups(user=&user,outds=&tempds1)
110
111 /* get list of groups with access for that table */
112 proc sql;
113 create table &tempds2 as
114 select distinct sas_group
115 from &&&cntl_lib_var...mpe_security
116 where &dc_dttmtfmt. lt tx_to
117 and access_level="&access_level"
118 and (
119 (libref="%scan(&base_table,1,.)" and upcase(dsn)="%scan(&base_table,2,.)")
120 or (libref="%scan(&base_table,1,.)" and dsn="*ALL*")
121 or (libref="*ALL*")
122 );
123 %if &_debug ge 131 %then %do;
124 data _null_;
125 set &tempds1;
126 putlog (_all_)(=);
127 run;
128 data _null_;
129 set &tempds2;
130 putlog (_all_)(=);
131 run;
132 %end;
133
134 proc sql;
135 create table &outds as
136 select * from &tempds1
137 where groupname="&mpeadmins"
138 or groupname in (select * from &tempds2);
139
140 %put &sysmacroname: base_table=&base_table;
141 %put &sysmacroname: access_level=&access_level;
142%mend mpe_accesscheck;