1 -- Regano database internal function definitions
3 -- Uses PostgreSQL extensions.
5 -- These functions are for internal use.
7 -- Regano is a domain registration system for OpenNIC TLDs written in
8 -- Perl. This file is part of Regano.
10 -- Regano may be distributed under the same terms as Perl itself. Of
11 -- particular importance, note that while regano is distributed in the
12 -- hope that it will be useful, there is NO WARRANTY OF ANY KIND
13 -- WHATSOEVER WHETHER EXPLICIT OR IMPLIED.
16 -- The type definitions in db_types.sql must already be installed.
17 -- The table definitions in db_tables.sql must already be installed.
19 CREATE OR REPLACE FUNCTION regano.config_set
20 (key text, value bigint)
23 PERFORM * FROM regano.config WHERE regano.config.key = config_set.key;
25 UPDATE regano.config SET number = value
26 WHERE regano.config.key = config_set.key;
28 INSERT INTO regano.config (key, number) VALUES (key, value);
31 $$ LANGUAGE plpgsql VOLATILE STRICT SECURITY INVOKER;
32 ALTER FUNCTION regano.config_set (text, bigint)
35 CREATE OR REPLACE FUNCTION regano.config_set
36 (key text, value interval)
39 PERFORM * FROM regano.config WHERE regano.config.key = config_set.key;
41 UPDATE regano.config SET interval = value
42 WHERE regano.config.key = config_set.key;
44 INSERT INTO regano.config (key, interval) VALUES (key, value);
47 $$ LANGUAGE plpgsql VOLATILE STRICT SECURITY INVOKER;
48 ALTER FUNCTION regano.config_set (text, interval)
51 CREATE OR REPLACE FUNCTION regano.config_set
52 (key text, value text)
55 PERFORM * FROM regano.config WHERE regano.config.key = config_set.key;
57 UPDATE regano.config SET text = value
58 WHERE regano.config.key = config_set.key;
60 INSERT INTO regano.config (key, text) VALUES (key, value);
63 $$ LANGUAGE plpgsql VOLATILE STRICT SECURITY INVOKER;
64 ALTER FUNCTION regano.config_set (text, text)
68 CREATE OR REPLACE FUNCTION regano.config_get (key text)
69 RETURNS regano.config AS $$
70 SELECT * FROM regano.config WHERE key = $1
71 $$ LANGUAGE SQL STABLE STRICT SECURITY INVOKER;
72 ALTER FUNCTION regano.config_get (text)
75 CREATE OR REPLACE FUNCTION regano.advance_timestamp_by_config_item
76 (timestamp with time zone, regano.config)
77 RETURNS timestamp with time zone AS $$
78 SELECT $1 + $2.interval
79 $$ LANGUAGE SQL IMMUTABLE STRICT SECURITY INVOKER;
80 ALTER FUNCTION regano.advance_timestamp_by_config_item
81 (timestamp with time zone, regano.config)
84 leftarg = timestamp with time zone,
85 rightarg = regano.config,
86 procedure = regano.advance_timestamp_by_config_item
90 CREATE OR REPLACE FUNCTION regano.contact_next_id (bigint)
92 SELECT COALESCE(MAX(id), 0) + 1
93 FROM regano.contacts WHERE owner_id = $1;
94 $$ LANGUAGE SQL STABLE STRICT SECURITY INVOKER;
95 ALTER FUNCTION regano.contact_next_id (bigint)
98 CREATE OR REPLACE FUNCTION regano.username (regano.sessions)
100 SELECT username FROM regano.users WHERE id = $1.user_id;
101 $$ LANGUAGE SQL STABLE STRICT SECURITY INVOKER;
102 ALTER FUNCTION regano.username (regano.sessions)
104 CREATE OR REPLACE FUNCTION regano.username (session_id uuid)
107 FROM regano.sessions JOIN regano.users
108 ON (regano.sessions.user_id = regano.users.id)
109 WHERE regano.sessions.id = $1;
110 $$ LANGUAGE SQL STABLE STRICT SECURITY INVOKER;
111 ALTER FUNCTION regano.username (uuid)
114 CREATE OR REPLACE FUNCTION regano.session_user_id (uuid) RETURNS bigint AS $$
115 SELECT user_id FROM regano.sessions WHERE id = $1
116 $$ LANGUAGE SQL STABLE STRICT SECURITY INVOKER;
117 ALTER FUNCTION regano.session_user_id (uuid)
120 CREATE OR REPLACE FUNCTION regano.zone_verify_access
121 (session_id uuid, zone_name regano.dns_fqdn, action text)
122 RETURNS regano.domains AS $$
124 user_id CONSTANT bigint NOT NULL
125 := regano.session_user_id(session_id);
127 primary_label regano.dns_label;
128 tail regano.dns_fqdn;
130 domain regano.domains%ROWTYPE;
132 primary_label := substring(zone_name from '^([^.]+)[.]');
133 tail := substring(zone_name from '^[^.]+([.].+[.])$');
135 SELECT * INTO STRICT domain
137 WHERE (lower(primary_label) = lower(domain_name))
138 AND (lower(tail) = lower(domain_tail));
140 IF user_id <> domain.owner_id THEN
142 'attempt made to modify zone (%) not belonging to current user (%): %',
143 zone_name, regano.username(session_id), action;
148 $$ LANGUAGE plpgsql STABLE STRICT SECURITY INVOKER;
149 ALTER FUNCTION regano.zone_verify_access (uuid, regano.dns_fqdn, text)
152 CREATE OR REPLACE FUNCTION regano.zone_verify_records
153 (domain regano.domains)
158 -- CNAME records must have unique labels among all records [RFC2181]
159 WITH aliases AS (SELECT domain_id, seq_no, name
160 FROM regano.domain_records
161 WHERE type = 'CNAME' AND domain_id = domain.id)
162 SELECT COUNT(*) INTO STRICT count
163 FROM aliases a INNER JOIN regano.domain_records r
164 USING (domain_id, name)
165 WHERE a.seq_no <> r.seq_no;
167 RAISE EXCEPTION 'CNAME and other data at same point in DNS zone';
170 -- DNAME records must have no descendants [RFC2672]
171 WITH aliases AS (SELECT domain_id, seq_no, name
172 FROM regano.domain_records
173 WHERE type = 'DNAME' AND domain_id = domain.id)
174 SELECT COUNT(*) INTO STRICT count
175 FROM aliases a INNER JOIN regano.domain_records r USING (domain_id)
176 WHERE a.seq_no <> r.seq_no AND r.name LIKE '%.'||a.name;
178 RAISE EXCEPTION 'other data found below DNAME';
181 $$ LANGUAGE plpgsql STABLE STRICT SECURITY INVOKER;
182 ALTER FUNCTION regano.zone_verify_records (regano.domains)
185 CREATE OR REPLACE FUNCTION regano.zone_next_seq_no (bigint)
187 SELECT COALESCE(MAX(seq_no), 0) + 1
188 FROM regano.domain_records WHERE domain_id = $1;
189 $$ LANGUAGE SQL STABLE STRICT SECURITY INVOKER;
190 ALTER FUNCTION regano.zone_next_seq_no (bigint)
193 CREATE OR REPLACE FUNCTION regano.canonicalize_record_name
194 (input regano.dns_name, zone_name regano.dns_fqdn)
195 RETURNS regano.dns_name AS $$
196 SELECT CASE WHEN lower($1) = lower($2) THEN regano.dns_name '@'
197 WHEN char_length($1) > (1+char_length($2))
198 AND (lower($1) LIKE lower('%.' || $2))
199 THEN CAST(substring($1 from 1
200 for (char_length($1) - char_length($2) - 1))
204 $$ LANGUAGE SQL IMMUTABLE STRICT SECURITY INVOKER;
205 ALTER FUNCTION regano.canonicalize_record_name
206 (regano.dns_name, regano.dns_fqdn)