comparison schema/manage_users.sql @ 268:72062ca52746

Make user_profiles table invisible for users users.list_users should be the single point to access user profile data. Keeping user_profiles visible would imply having to maintain RLS policies that are otherwise obsolete. Tests run as superuser still use user_profiles, because list_users does not show any data to a superuser.
author Tom Gottfried <tom@intevation.de>
date Mon, 30 Jul 2018 11:38:09 +0200
parents 13ad969a9138
children 0b2d9f96ddb8
comparison
equal deleted inserted replaced
267:7f030ec3472d 268:72062ca52746
25 25
26 26
27 -- Security-definer function to get current users country, which allows to 27 -- Security-definer function to get current users country, which allows to
28 -- restrict the view on user_profiles by country without infinite recursion 28 -- restrict the view on user_profiles by country without infinite recursion
29 CREATE FUNCTION current_user_country() 29 CREATE FUNCTION current_user_country()
30 RETURNS users.user_profiles.country%TYPE 30 RETURNS internal.user_profiles.country%TYPE
31 AS $$ 31 AS $$
32 SELECT country FROM users.user_profiles WHERE username = session_user 32 SELECT country FROM internal.user_profiles
33 WHERE username = session_user
33 $$ 34 $$
34 LANGUAGE SQL 35 LANGUAGE SQL
35 SECURITY DEFINER 36 SECURITY DEFINER
36 STABLE PARALLEL SAFE; 37 STABLE PARALLEL SAFE;
37 38
41 SELECT rolname 42 SELECT rolname
42 FROM pg_roles r JOIN pg_auth_members a ON r.oid = a.roleid 43 FROM pg_roles r JOIN pg_auth_members a ON r.oid = a.roleid
43 WHERE member = ( 44 WHERE member = (
44 SELECT oid FROM pg_roles WHERE rolname = current_user)) 45 SELECT oid FROM pg_roles WHERE rolname = current_user))
45 SELECT r.rolname, p.* 46 SELECT r.rolname, p.*
46 FROM cur, users.user_profiles p 47 FROM cur, internal.user_profiles p
47 JOIN pg_roles u ON p.username = u.rolname 48 JOIN pg_roles u ON p.username = u.rolname
48 JOIN pg_auth_members a ON u.oid = a.member 49 JOIN pg_auth_members a ON u.oid = a.member
49 JOIN pg_roles r ON a.roleid = r.oid 50 JOIN pg_roles r ON a.roleid = r.oid
50 WHERE p.username = current_user 51 WHERE p.username = current_user
51 OR cur.rolname = 'waterway_admin' 52 OR cur.rolname = 'waterway_admin'
53 OR cur.rolname = 'sys_admin'; 54 OR cur.rolname = 'sys_admin';
54 55
55 56
56 CREATE OR REPLACE FUNCTION sys_admin.create_user( 57 CREATE OR REPLACE FUNCTION sys_admin.create_user(
57 userrole varchar, 58 userrole varchar,
58 username users.user_profiles.username%TYPE, 59 username internal.user_profiles.username%TYPE,
59 pw varchar, 60 pw varchar,
60 country users.user_profiles.country%TYPE, 61 country internal.user_profiles.country%TYPE,
61 map_extent users.user_profiles.map_extent%TYPE, 62 map_extent internal.user_profiles.map_extent%TYPE,
62 email_address users.user_profiles.email_address%TYPE 63 email_address internal.user_profiles.email_address%TYPE
63 ) 64 )
64 RETURNS void 65 RETURNS void
65 AS $$ 66 AS $$
66 BEGIN 67 BEGIN
67 IF map_extent IS NULL 68 IF map_extent IS NULL
68 THEN 69 THEN
69 map_extent = ST_Extent(area) FROM users.responsibility_areas ra 70 map_extent = ST_Extent(area) FROM users.responsibility_areas ra
70 WHERE ra.country = create_user.country; 71 WHERE ra.country = create_user.country;
71 END IF; 72 END IF;
72 INSERT INTO users.user_profiles VALUES ( 73 INSERT INTO internal.user_profiles (
73 username, country, map_extent, email_address); 74 username, country, map_extent, email_address)
75 VALUES (username, country, map_extent, email_address);
74 EXECUTE format( 76 EXECUTE format(
75 'CREATE ROLE %I IN ROLE %I LOGIN PASSWORD %L', 77 'CREATE ROLE %I IN ROLE %I LOGIN PASSWORD %L',
76 username, 78 username,
77 userrole, 79 userrole,
78 users.check_password(pw)); 80 users.check_password(pw));
81 LANGUAGE plpgsql 83 LANGUAGE plpgsql
82 SECURITY DEFINER; 84 SECURITY DEFINER;
83 85
84 86
85 CREATE OR REPLACE FUNCTION sys_admin.update_user( 87 CREATE OR REPLACE FUNCTION sys_admin.update_user(
86 username users.user_profiles.username%TYPE, 88 username internal.user_profiles.username%TYPE,
87 new_userrole varchar, 89 new_userrole varchar,
88 new_username users.user_profiles.username%TYPE, 90 new_username internal.user_profiles.username%TYPE,
89 new_pw varchar, 91 new_pw varchar,
90 new_country users.user_profiles.country%TYPE, 92 new_country internal.user_profiles.country%TYPE,
91 new_map_extent users.user_profiles.map_extent%TYPE, 93 new_map_extent internal.user_profiles.map_extent%TYPE,
92 new_email_address users.user_profiles.email_address%TYPE 94 new_email_address internal.user_profiles.email_address%TYPE
93 ) 95 )
94 RETURNS void 96 RETURNS void
95 AS $$ 97 AS $$
96 DECLARE 98 DECLARE
97 cur_username name; 99 cur_username name;
98 cur_userrole name; 100 cur_userrole name;
99 BEGIN 101 BEGIN
100 cur_username = username; 102 cur_username = username;
101 103
102 UPDATE users.user_profiles p 104 UPDATE internal.user_profiles p
103 SET (username, country, map_extent, email_address) 105 SET (username, country, map_extent, email_address)
104 = (new_username, new_country, new_map_extent, new_email_address) 106 = (new_username, new_country, new_map_extent, new_email_address)
105 WHERE p.username = cur_username; 107 WHERE p.username = cur_username;
106 108
107 IF new_username <> cur_username 109 IF new_username <> cur_username
137 LANGUAGE plpgsql 139 LANGUAGE plpgsql
138 SECURITY DEFINER; 140 SECURITY DEFINER;
139 141
140 142
141 CREATE OR REPLACE FUNCTION sys_admin.delete_user( 143 CREATE OR REPLACE FUNCTION sys_admin.delete_user(
142 username users.user_profiles.username%TYPE 144 username internal.user_profiles.username%TYPE
143 ) 145 )
144 RETURNS void 146 RETURNS void
145 AS $$ 147 AS $$
146 DECLARE 148 DECLARE
147 bid int; 149 bid int;
154 -- in which this function is executed will not be terminated but lost 156 -- in which this function is executed will not be terminated but lost
155 -- without any privileges after commiting this transaction 157 -- without any privileges after commiting this transaction
156 158
157 -- Delete user 159 -- Delete user
158 EXECUTE format('DROP ROLE %I', username); 160 EXECUTE format('DROP ROLE %I', username);
159 DELETE FROM users.user_profiles p WHERE p.username = delete_user.username; 161 DELETE FROM internal.user_profiles p
162 WHERE p.username = delete_user.username;
160 END; 163 END;
161 $$ 164 $$
162 LANGUAGE plpgsql 165 LANGUAGE plpgsql
163 SECURITY DEFINER; 166 SECURITY DEFINER;