-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy path08-ownership.sql
139 lines (117 loc) · 4.43 KB
/
08-ownership.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
-- sql/08-ownership.sql SQL Migration
CREATE OR REPLACE FUNCTION is_admin_or_owns(
nick LABEL,
exts TEXT[]
) RETURNS BOOLEAN LANGUAGE plpgsql STABLE AS $$
DECLARE
ret BOOLEAN;
BEGIN
-- Admins can just do it.
PERFORM true FROM users WHERE nickname = nick AND is_admin;
IF FOUND THEN RETURN TRUE; END IF;
-- Permission granted only if the user owns all extensions.
SELECT bool_and(COALESCE(owner = nick, FALSE))
INTO ret
FROM unnest(exts) AS ext
LEFT JOIN extensions e ON ext = e.name;
RETURN COALESCE(ret, false);
END;
$$;
-- Disallow end-user from using this function.
REVOKE ALL ON FUNCTION is_admin_or_owns(LABEL, TEXT[]) FROM PUBLIC;
CREATE OR REPLACE FUNCTION grant_coownership(
nick LABEL,
coowner LABEL,
exts TEXT[]
) RETURNS BOOLEAN LANGUAGE PLPGSQL SECURITY DEFINER AS $$
/*
% SELECT grant_coownership('theory', 'strongrrl', ARRAY['pair', 'pgtap']);
grant_coownership
───────────────────
t
Grants co-ownership to one or more extensions. The first argument is the
nickname of the user inserting the co-owner. Said user must either be and
admin or own *all* of the specified extensions. The second argument is the
nickname of the user being granted co-ownership. This name must not be the
same name as the owner. The third argument is an array of the names of the
extensions to which co-ownership is to be granted.
*/
BEGIN
IF NOT is_admin_or_owns(nick, exts) THEN
RAISE EXCEPTION 'User “%” does not have permission to grant co-ownership to “%”',
nick, array_to_string(exts, '”, “');
END IF;
-- Grant only if the target is not already owner or co-owner.
INSERT INTO coowners (extension, nickname)
SELECT e.name, coowner
FROM extensions e
LEFT JOIN coowners c ON e.name = c.extension AND c.nickname = coowner
WHERE e.name = ANY(exts)
AND e.owner <> coowner
AND c.nickname IS NULL;
RETURN FOUND;
END;
$$;
CREATE OR REPLACE FUNCTION revoke_coownership(
nick LABEL,
coowner LABEL,
exts TEXT[]
) RETURNS BOOLEAN LANGUAGE PLPGSQL SECURITY DEFINER AS $$
/*
% SELECT revoke_coownership('theory', 'strongrrl', ARRAY['pair', 'pgtap']);
revoke_coownership
────────────────────
t
Remove co-ownership permission to the specified extensions. The first argument
is the nickname of the user removing co-ownership. Said user must either be
and admin, own *all* of the specified extensions, or be removing co-ownership
from itself. The second argument is the nickname of the user being for whom
co-ownership is being removed. The third argument is an array of the names of
the extensions from which co-ownership is to be removed.
*/
BEGIN
IF NOT is_admin_or_owns(nick, exts) AND nick <> coowner THEN
RAISE EXCEPTION 'User “%” does not have permission to revoke co-ownership from “%”',
nick, array_to_string(exts, '”, “');
END IF;
DELETE FROM coowners
WHERE nickname = coowner
AND extension = ANY(exts);
RETURN FOUND;
END;
$$;
CREATE OR REPLACE FUNCTION transfer_ownership(
nick LABEL,
newowner LABEL,
exts TEXT[]
) RETURNS BOOLEAN LANGUAGE PLPGSQL SECURITY DEFINER AS $$
/*
% SELECT transfer_ownership('theory', 'strongrrl', ARRAY['pair', 'pgtap']);
transfer_ownership
────────────────────
t
Transfer ownership of the specified extensions to a new owner. The first
argument is the nickname of the user performing the transfer. Said user must
either be and admin or own *all* of the specified extensions. The second
argument is the nickname of the user being given ownership. This name must not
be the same name as the owner. The third argument is an array of the names of
the extensions to which ownership is to be transferred.
*/
BEGIN
IF NOT is_admin_or_owns(nick, exts) THEN
RAISE EXCEPTION 'User “%” does not have permission to transfer ownership of “%”',
nick, array_to_string(exts, '”, “');
END IF;
-- Remove any co-ownerships.
DELETE FROM coowners
WHERE nickname = newowner
AND extension = ANY(exts);
-- Make the new guy the boss.
UPDATE extensions
SET owner = newowner,
updated_at = NOW()
WHERE name = ANY(exts)
AND owner <> newowner;
RETURN FOUND;
END;
$$;