diff --git a/dba/appuser_permissions.txt b/dba/appuser_permissions.txt
index 71cf4842..325af656 100644
--- a/dba/appuser_permissions.txt
+++ b/dba/appuser_permissions.txt
@@ -42,7 +42,6 @@ GRANT SELECT,UPDATE
ON usr_user_no_seq
ON roles_role_no_seq
ON session_session_id_seq
- ON principal_principal_id_seq
ON principal_type_principal_type_id_seq
ON sync_tokens_sync_token_seq
diff --git a/dba/base-data.sql b/dba/base-data.sql
index c69de848..35509ea1 100644
--- a/dba/base-data.sql
+++ b/dba/base-data.sql
@@ -20,13 +20,13 @@ SELECT setval('usr_user_no_seq', (SELECT 1000 UNION SELECT user_no FROM usr ORDE
INSERT INTO relationship_type ( rt_id, rt_name, confers, bit_confers )
VALUES( 1, 'Administers', 'A', privilege_to_bits('DAV::all') );
-INSERT INTO relationship_type ( rt_id, rt_name, confers )
+INSERT INTO relationship_type ( rt_id, rt_name, confers, bit_confers )
VALUES( 2, 'Can read/write to', 'RW', privilege_to_bits( ARRAY['DAV::read','DAV::write']) );
-INSERT INTO relationship_type ( rt_id, rt_name, confers )
+INSERT INTO relationship_type ( rt_id, rt_name, confers, bit_confers )
VALUES( 3, 'Can read from', 'R', privilege_to_bits( 'DAV::read') );
-INSERT INTO relationship_type ( rt_id, rt_name, confers )
+INSERT INTO relationship_type ( rt_id, rt_name, confers, bit_confers )
VALUES( 4, 'Can see free/busy time of', 'F', privilege_to_bits( 'caldav:read-free-busy') );
INSERT INTO principal_type (principal_type_id, principal_type_desc) VALUES( 1, 'Person' );
diff --git a/dba/caldav_functions.sql b/dba/caldav_functions.sql
index 35231ea7..b8e136ac 100644
--- a/dba/caldav_functions.sql
+++ b/dba/caldav_functions.sql
@@ -246,7 +246,7 @@ CREATE or REPLACE FUNCTION usr_is_role( INT, TEXT ) RETURNS BOOLEAN AS $$
SELECT EXISTS( SELECT 1 FROM role_member JOIN roles USING(role_no) WHERE role_member.user_no=$1 AND roles.role_name=$2 )
$$ LANGUAGE 'sql' IMMUTABLE STRICT;
-CREATE or REPLACE FUNCTION get_permissions( INT, INT ) RETURNS TEXT AS $$
+CREATE or REPLACE FUNCTION legacy_get_permissions( INT, INT ) RETURNS TEXT AS $$
DECLARE
in_from ALIAS FOR $1;
in_to ALIAS FOR $2;
diff --git a/dba/davical.sql b/dba/davical.sql
index 6e8ff66c..4e586892 100644
--- a/dba/davical.sql
+++ b/dba/davical.sql
@@ -38,6 +38,31 @@ END
$$
LANGUAGE 'PlPgSQL' IMMUTABLE STRICT;
+-- Given an array of verbose DAV: or CalDAV: privilege names return the bitmask
+CREATE or REPLACE FUNCTION privilege_to_bits( TEXT[] ) RETURNS BIT(24) AS $$
+DECLARE
+ raw_privs ALIAS FOR $1;
+ in_priv TEXT;
+ out_bits BIT(24);
+ i INT;
+ all BIT(24);
+ start INT;
+ finish INT;
+BEGIN
+ out_bits := 0::BIT(24);
+ all := ~ out_bits;
+ SELECT array_lower(raw_privs,1) INTO start;
+ SELECT array_upper(raw_privs,1) INTO finish;
+ FOR i IN start .. finish LOOP
+ SELECT out_bits | privilege_to_bits(raw_privs[i]) INTO out_bits;
+ IF out_bits = all THEN
+ RETURN all;
+ END IF;
+ END LOOP;
+ RETURN out_bits;
+END
+$$
+LANGUAGE 'PlPgSQL' IMMUTABLE STRICT;
-- This sequence is used in a number of places so that any DAV resource will have a unique ID
@@ -139,7 +164,7 @@ CREATE TABLE relationship_type (
rt_togroup BOOLEAN,
confers TEXT DEFAULT 'RW',
rt_fromgroup BOOLEAN,
- bit_confers BIT(24) DEFAULT legacy_privilege_to_bits('RW')
+ bit_confers BIT(24) DEFAULT privilege_to_bits(ARRAY['DAV::read','DAV::write'])
);
@@ -147,7 +172,7 @@ CREATE TABLE relationship (
from_user INT REFERENCES usr (user_no) ON UPDATE CASCADE ON DELETE CASCADE,
to_user INT REFERENCES usr (user_no) ON UPDATE CASCADE ON DELETE CASCADE,
rt_id INT REFERENCES relationship_type (rt_id) ON UPDATE CASCADE ON DELETE CASCADE,
- bit_confers BIT(24) DEFAULT legacy_privilege_to_bits('RW'),
+ confers BIT(24) DEFAULT privilege_to_bits(ARRAY['DAV::read','DAV::write']),
PRIMARY KEY ( from_user, to_user, rt_id )
);
@@ -230,9 +255,8 @@ CREATE TABLE principal_type (
-- web needs SELECT,INSERT,UPDATE,DELETE
-DROP TABLE principal CASCADE;
CREATE TABLE principal (
- principal_id DEFAULT nextval('dav_id_seq') PRIMARY KEY,
+ principal_id INT8 DEFAULT nextval('dav_id_seq') PRIMARY KEY,
type_id INT8 NOT NULL REFERENCES principal_type(principal_type_id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE,
user_no INT8 NULL REFERENCES usr(user_no) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE,
displayname TEXT,
diff --git a/dba/patches/1.2.6.sql b/dba/patches/1.2.6.sql
index 613aa1dc..36cedef6 100644
--- a/dba/patches/1.2.6.sql
+++ b/dba/patches/1.2.6.sql
@@ -498,7 +498,7 @@ ALTER TABLE relationship_type ADD COLUMN bit_confers BIT(24) DEFAULT privilege_t
UPDATE relationship_type SET bit_confers = legacy_privilege_to_bits(confers);
ALTER TABLE relationship ADD COLUMN confers BIT(24) DEFAULT privilege_to_bits('caldav:read-free-busy');
-UPDATE relationship r SET confers = bit_confers FROM relationship_type rt WHERE rt.rt_id=r.rt_id;
+UPDATE relationship r SET confers = (SELECT bit_confers FROM relationship_type rt WHERE rt.rt_id=r.rt_id);
ALTER TABLE collection ADD COLUMN default_privileges BIT(24) DEFAULT privilege_to_bits('caldav:read-free-busy');
@@ -509,7 +509,7 @@ INSERT INTO principal_type (principal_type_id, principal_type_desc) VALUES( 3, '
-- web needs SELECT,INSERT,UPDATE,DELETE
DROP TABLE principal CASCADE;
CREATE TABLE principal (
- principal_id DEFAULT nextval('dav_id_seq') PRIMARY KEY,
+ principal_id INT8 DEFAULT nextval('dav_id_seq') PRIMARY KEY,
type_id INT8 NOT NULL REFERENCES principal_type(principal_type_id) ON UPDATE CASCADE ON DELETE RESTRICT DEFERRABLE,
user_no INT8 NULL REFERENCES usr(user_no) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE,
displayname TEXT,
diff --git a/dba/sample-data.sql b/dba/sample-data.sql
index edf5fcf2..b0ef3677 100644
--- a/dba/sample-data.sql
+++ b/dba/sample-data.sql
@@ -28,8 +28,10 @@ INSERT INTO usr ( user_no, active, email_ok, updated, username, password, fullna
INSERT INTO usr ( user_no, active, email_ok, updated, username, password, fullname, email )
VALUES( 100, TRUE, current_date, current_date, 'resource1', '*salt*unpossible', 'Resource 1', 'resource1@example.net' );
+INSERT INTO role_member (user_no, role_no) VALUES( 100, 3);
INSERT INTO usr ( user_no, active, email_ok, updated, username, password, fullname, email )
VALUES( 101, TRUE, current_date, current_date, 'resource2', '*salt*unpossible', 'Resource 2', 'resource2@example.net' );
+INSERT INTO role_member (user_no, role_no) VALUES( 101, 3);
INSERT INTO usr ( user_no, active, email_ok, updated, username, password, fullname, email )
VALUES( 200, TRUE, current_date, current_date, 'resmgr1', '*salt*unpossible', 'Resource Managers', 'resource-managers@example.net' );
@@ -45,10 +47,24 @@ UPDATE usr SET joined = '2009-06-01', updated = '2009-06-02';
INSERT INTO collection (user_no, parent_container, dav_name, dav_etag,
dav_displayname, is_calendar, created, modified,
- public_events_only, publicly_readable, collection_id)
+ public_events_only, publicly_readable, collection_id, resourcetypes )
SELECT user_no, '/' || username || '/', '/' || username || '/home/', md5(username),
username || ' home', TRUE, '2009-06-03', '2009-06-04',
- FALSE, FALSE, user_no FROM usr;
+ FALSE, FALSE, user_no, ''
+ FROM usr;
+
+INSERT INTO principal (type_id, user_no, displayname, active, default_privileges)
+ SELECT 1, user_no, fullname, active, privilege_to_bits(ARRAY['read-free-busy','schedule-send','schedule-deliver']) FROM usr
+ WHERE NOT EXISTS(SELECT 1 FROM role_member JOIN roles USING(role_no) WHERE role_name = 'Group' AND role_member.user_no = usr.user_no)
+ AND NOT EXISTS(SELECT 1 FROM role_member JOIN roles USING(role_no) WHERE role_name = 'Resource' AND role_member.user_no = usr.user_no) ;
+
+INSERT INTO principal (type_id, user_no, displayname, active, default_privileges)
+ SELECT 2, user_no, fullname, active, privilege_to_bits(ARRAY['read','schedule-send','schedule-deliver']) FROM usr
+ WHERE EXISTS(SELECT 1 FROM role_member JOIN roles USING(role_no) WHERE role_name = 'Resource' AND role_member.user_no = usr.user_no);
+
+INSERT INTO principal (type_id, user_no, displayname, active, default_privileges)
+ SELECT 3, user_no, fullname, active, privilege_to_bits(ARRAY['read-free-busy','schedule-send','schedule-deliver']) FROM usr
+ WHERE EXISTS(SELECT 1 FROM role_member JOIN roles USING(role_no) WHERE role_name = 'Group' AND role_member.user_no = usr.user_no);
SELECT setval('dav_id_seq', 1000);
@@ -68,11 +84,32 @@ INSERT INTO relationship ( from_user, to_user, rt_id ) VALUES( 30, 200, 1 );
INSERT INTO relationship ( from_user, to_user, rt_id ) VALUES( 30, 20, 2 );
INSERT INTO relationship ( from_user, to_user, rt_id ) VALUES( 30, 10, 2 );
+
-- Between a team
INSERT INTO relationship ( from_user, to_user, rt_id ) VALUES( 20, 300, 3 );
INSERT INTO relationship ( from_user, to_user, rt_id ) VALUES( 10, 300, 3 );
INSERT INTO relationship ( from_user, to_user, rt_id ) VALUES( 30, 300, 3 );
+INSERT INTO relationship ( from_user, to_user, rt_id ) VALUES( 300, 20, 3 );
+INSERT INTO relationship ( from_user, to_user, rt_id ) VALUES( 300, 10, 3 );
+INSERT INTO relationship ( from_user, to_user, rt_id ) VALUES( 300, 30, 3 );
-- Granting explicit free/busy permission
INSERT INTO relationship ( from_user, to_user, rt_id ) VALUES( 11, 10, 4 );
INSERT INTO relationship ( from_user, to_user, rt_id ) VALUES( 10, 11, 4 );
+
+
+UPDATE relationship r SET confers = (SELECT bit_confers FROM relationship_type rt WHERE rt.rt_id=r.rt_id);
+
+INSERT INTO group_member ( group_id, member_id)
+ SELECT g.principal_id, m.principal_id
+ FROM relationship JOIN principal g ON(to_user=g.user_no AND g.type_id = 3) -- Group
+ JOIN principal m ON(from_user=m.user_no AND m.type_id = 1); -- Person
+
+INSERT INTO grants ( by_principal, dav_name, to_principal, privileges, is_group )
+ SELECT pby.principal_id AS by_principal, '/' ||t.username||'/' AS dav_name, pto.principal_id AS to_principal,
+ confers AS privileges, pto.type_id > 2 AS is_group
+ FROM relationship r JOIN usr f ON(f.user_no=r.from_user)
+ JOIN usr t ON(t.user_no=r.to_user)
+ JOIN principal pby ON(t.user_no=pby.user_no)
+ JOIN principal pto ON(pto.user_no=f.user_no)
+ WHERE rt_id < 4 AND pby.type_id < 3;
diff --git a/testing/tests/regression-suite/524-iCal-PROPFIND.result b/testing/tests/regression-suite/524-iCal-PROPFIND.result
index 124b844b..09281589 100644
--- a/testing/tests/regression-suite/524-iCal-PROPFIND.result
+++ b/testing/tests/regression-suite/524-iCal-PROPFIND.result
@@ -1,8 +1,8 @@
HTTP/1.1 207 Multi-Status
Date: Dow, 01 Jan 2000 00:00:00 GMT
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule, extended-mkcol
-ETag: "432aa6b31d8dbe82651aef6bac55ea55"
-Content-Length: 3515
+ETag: "cc705bcb25130c21378d93e32747c072"
+Content-Length: 3601
Content-Type: text/xml; charset="utf-8"
@@ -75,6 +75,7 @@ Content-Type: text/xml; charset="utf-8"
/caldav.php/user1/
+ /caldav.php/teamclient1/
/caldav.php/teamclient1/
@@ -82,9 +83,10 @@ Content-Type: text/xml; charset="utf-8"
/caldav.php/assistant1/calendar-proxy-read/
/manager1/calendar-proxy-read/
- "d6996992ae401eb02ed8fed0bfb22895"
+ "81833b8410a85c2e86dd32ae4470e72b"
/caldav.php/user1/
+ /caldav.php/teamclient1/
HTTP/1.1 200 OK
diff --git a/testing/tests/regression-suite/553-iPhone-PROPFIND.result b/testing/tests/regression-suite/553-iPhone-PROPFIND.result
index f7e83a01..7558f9ae 100644
--- a/testing/tests/regression-suite/553-iPhone-PROPFIND.result
+++ b/testing/tests/regression-suite/553-iPhone-PROPFIND.result
@@ -1,7 +1,7 @@
HTTP/1.1 207 Multi-Status
Date: Dow, 01 Jan 2000 00:00:00 GMT
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule, extended-mkcol
-ETag: "67c73d7155944138de99f14a0872e727"
+ETag: "5771fd61ef8348f364c7fc69c578028a"
Transfer-Encoding: chunked
Content-Type: text/xml; charset="utf-8"
@@ -285,7 +285,7 @@ Content-Type: text/xml; charset="utf-8"
/user1/calendar-proxy-read/
- "3646538a5bdbcc9a144ee36f36000214"
+ "c26fa324d66fa84a0da8e1ec8c4566fd"
diff --git a/testing/tests/regression-suite/554-iPhone-PROPFIND.result b/testing/tests/regression-suite/554-iPhone-PROPFIND.result
index f7e83a01..7558f9ae 100644
--- a/testing/tests/regression-suite/554-iPhone-PROPFIND.result
+++ b/testing/tests/regression-suite/554-iPhone-PROPFIND.result
@@ -1,7 +1,7 @@
HTTP/1.1 207 Multi-Status
Date: Dow, 01 Jan 2000 00:00:00 GMT
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule, extended-mkcol
-ETag: "67c73d7155944138de99f14a0872e727"
+ETag: "5771fd61ef8348f364c7fc69c578028a"
Transfer-Encoding: chunked
Content-Type: text/xml; charset="utf-8"
@@ -285,7 +285,7 @@ Content-Type: text/xml; charset="utf-8"
/user1/calendar-proxy-read/
- "3646538a5bdbcc9a144ee36f36000214"
+ "c26fa324d66fa84a0da8e1ec8c4566fd"