I know the database design below might not be 'clean', however, it seems to break MySQL 5.0.38 for some reason.
--
-- Table structure for table `db_database`
--
DROP DATABASE IF EXISTS system;
CREATE DATABASE IF NOT EXISTS system;
USE system;
DROP TABLE IF EXISTS `db_database`;
CREATE TABLE IF NOT EXISTS `db_database` (
`id` int(11) NOT NULL auto_increment,
`db_name` varchar(255) NOT NULL,
`is_enabled` tinyint(1) NOT NULL default 0,
`system_user_id` int(11) NOT NULL REFERENCES system_user(id),
`timestamp` timestamp NOT NULL default NOW() on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `db_database_user`
--
DROP TABLE IF EXISTS `db_database_user`;
CREATE TABLE IF NOT EXISTS `db_database_user` (
`id` int(11) NOT NULL auto_increment,
`db_user_id` int(11) NOT NULL REFERENCES db_user(id),
`db_database_id` int(11) NOT NULL REFERENCES db_database(id),
`priv_select` tinyint(1) NOT NULL default 0,
`priv_insert` tinyint(1) NOT NULL default 0,
`priv_update` tinyint(1) NOT NULL default 0,
`priv_delete` tinyint(1) NOT NULL default 0,
`priv_create_table` tinyint(1) default NULL default 0,
`priv_drop_table` tinyint(1) NOT NULL default 0,
`timestamp` timestamp NOT NULL default NOW() on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `db_user_id` (`db_user_id`),
KEY `db_database_id` (`db_database_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `db_user`
--
DROP TABLE IF EXISTS `db_user`;
CREATE TABLE IF NOT EXISTS `db_user` (
`id` int(11) NOT NULL auto_increment,
`db_username` varchar(16) NOT NULL UNIQUE,
`db_password` varchar(16) NOT NULL,
`is_enabled` tinyint(1) NOT NULL default 0,
`timestamp` timestamp NOT NULL default NOW() on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `mail_admin_users`
--
DROP TABLE IF EXISTS `mail_admin_user`;
CREATE TABLE IF NOT EXISTS `mail_admin_user` (
`id` int(11) NOT NULL auto_increment,
`mail_domain_id` int(11) NOT NULL REFERENCES mail_domain(id),
`system_user_id` int(11) NOT NULL REFERENCES system_user(id),
`timestamp` timestamp NOT NULL default NOW() on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `mail_domain_id` (`mail_domain_id`),
KEY `system_user_id` (`system_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `mail_alias`
--
DROP TABLE IF EXISTS `mail_alias`;
CREATE TABLE IF NOT EXISTS `mail_alias` (
`id` int(11) NOT NULL auto_increment,
`alias_localpart` varchar(255) NOT NULL,
`alias_remote` varchar(255) NOT NULL,
`is_enabled` tinyint(1) NOT NULL default 0,
`alias_password` varchar(32) default NULL,
`timestamp` timestamp NOT NULL default NOW() on update CURRENT_TIMESTAMP,
`mail_domain_id` int(11) NOT NULL REFERENCES mail_domain(id),
`system_user_id` int(11) NOT NULL REFERENCES system_user(id),
PRIMARY KEY (`id`),
KEY `mail_domain_id` (`mail_domain_id`),
KEY `system_user_id` (`system_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `mail_alias_domain`
--
DROP TABLE IF EXISTS `mail_alias_domain`;
CREATE TABLE IF NOT EXISTS `mail_alias_domain` (
`id` int(11) NOT NULL auto_increment,
`alias_name` varchar(255) NOT NULL UNIQUE,
`mail_domain_id` int(11) NOT NULL REFERENCES mail_domain(id),
`timestamp` timestamp NOT NULL default NOW() on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `mail_domain_id` (`mail_domain_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `mail_box`
--
DROP TABLE IF EXISTS `mail_box`;
CREATE TABLE IF NOT EXISTS `mail_box` (
`id` int(11) NOT NULL auto_increment,
`box_localpart` varchar(255) NOT NULL,
`is_enabled` tinyint(1) NOT NULL default 0,
`box_password` varchar(32) NOT NULL,
`timestamp` timestamp NOT NULL default NOW() on update CURRENT_TIMESTAMP,
`mail_domain_id` int(11) NOT NULL REFERENCES mail_domain(id),
`system_user_id` int(11) NOT NULL REFERENCES system_user(id),
PRIMARY KEY (`id`),
KEY `mail_domain_id` (`mail_domain_id`),
KEY `system_user_id` (`system_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `mail_domain`
--
DROP TABLE IF EXISTS `mail_domain`;
CREATE TABLE IF NOT EXISTS `mail_domain` (
`id` int(11) NOT NULL auto_increment,
`domain_name` varchar(255) NOT NULL UNIQUE,
`is_enabled` tinyint(1) NOT NULL default 0,
`system_group_id` int(11) NOT NULL REFERENCES system_group(id),
`timestamp` timestamp NOT NULL default NOW() on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `system_group_id` (`system_group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `system_group`
--
DROP TABLE IF EXISTS `system_group`;
CREATE TABLE IF NOT EXISTS `system_group` (
`id` int(11) NOT NULL auto_increment,
`sys_gid` int(11) NOT NULL UNIQUE,
`sys_groupname` varchar(16) NOT NULL UNIQUE,
`is_enabled` tinyint(1) NOT NULL,
`timestamp` timestamp NOT NULL default NOW()
ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `system_group_membership`
--
DROP TABLE IF EXISTS `system_group_membership`;
CREATE TABLE IF NOT EXISTS `system_group_membership` (
`id` int(11) NOT NULL auto_increment,
`system_group_id` int(11) NOT NULL REFERENCES system_group(id),
`system_user_id` int(11) NOT NULL REFERENCES system_user(id),
`timestamp` timestamp NOT NULL default NOW()
ON UPDATE CURRENT_TIMESTAMP,
`group_admin` tinyint(1) NOT NULL default 0,
`mark_delete` tinyint(1) NOT NULL default 0,
PRIMARY KEY (`id`),
KEY `system_group_id` (`system_group_id`),
KEY `system_user_id` (`system_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `system_user`
--
DROP TABLE IF EXISTS `system_user`;
CREATE TABLE IF NOT EXISTS `system_user` (
`id` int(11) NOT NULL auto_increment,
`sys_uid` int(11) NOT NULL UNIQUE,
`sys_username` varchar(16) NOT NULL UNIQUE,
`email` varchar(255) NOT NULL,
`system_group_id` int(11) NOT NULL REFERENCES system_group(id),
`sys_password` varchar(32) default NULL,
`sys_shell` varchar(32) NOT NULL default '/bin/bash',
`is_enabled` tinyint(1) NOT NULL default 0,
`sys_gecos` varchar(255) NOT NULL,
`timestamp` timestamp NOT NULL default NOW() on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `system_group_id` (`system_group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `web_site`
--
DROP TABLE IF EXISTS `web_site`;
CREATE TABLE IF NOT EXISTS `web_site` (
`id` int(11) NOT NULL auto_increment,
`site_name` varchar(255) NOT NULL UNIQUE,
`site_admin_email` varchar(255) NOT NULL,
`is_enabled` tinyint(1) NOT NULL default 0,
`timestamp` timestamp NOT NULL default NOW() on update CURRENT_TIMESTAMP,
`system_group_id` int(11) NOT NULL REFERENCES system_group(id),
PRIMARY KEY (`id`),
KEY `system_group_id` (`system_group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Table structure for table `web_site_alias`
--
DROP TABLE IF EXISTS `web_site_alias`;
CREATE TABLE IF NOT EXISTS `web_site_alias` (
`id` int(11) NOT NULL auto_increment,
`site_alias_name` varchar(255) NOT NULL UNIQUE,
`timestamp` timestamp NOT NULL default NOW() on update CURRENT_TIMESTAMP,
`web_site_id` int(11) NOT NULL REFERENCES web_site(id),
PRIMARY KEY (`id`),
KEY `web_site_id` (`web_site_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
DROP TABLE IF EXISTS `web_site_user`;
CREATE TABLE IF NOT EXISTS `web_site_user` (
`web_site_id` int(11) NOT NULL REFERENCES web_site(id),
`system_user_id` int(11) NOT NULL REFERENCES system_user(id),
`site_admin` tinyint(1) NOT NULL default 0,
`timestamp` timestamp NOT NULL default NOW() on update CURRENT_TIMESTAMP,
PRIMARY KEY (`web_site_id`, `system_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- requests table
--
DROP TABLE IF EXISTS `request`;
CREATE TABLE IF NOT EXISTS `request` (
`id` int(11) NOT NULL auto_increment,
`request_type_id` int(11) NOT NULL REFERENCES request_type(id),
`system_user_id` int(11) NOT NULL REFERENCES system_user(id),
`activated` tinyint(1) NOT NULL default 0,
`done` tinyint(1) NOT NULL default 0,
`timestamp` timestamp NOT NULL default NOW() on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `request_type_id` (`request_type_id`),
KEY `system_user_id` (`system_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `request_type`;
CREATE TABLE IF NOT EXISTS `request_type` (
`id` int(11) NOT NULL auto_increment,
`type_name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `request_comment`;
CREATE TABLE IF NOT EXISTS `request_comment` (
`id` int(11) NOT NULL auto_increment,
`comment_text` TEXT NOT NULL,
`system_user_id` int(11) NOT NULL REFERENCES system_user(id),
`request_id` int(11) NOT NULL REFERENCES request(id),
`timestamp` timestamp NOT NULL DEFAULT NOW() on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `system_user_id` (`system_user_id`),
KEY `request_id` (`request_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `request_attr`;
CREATE TABLE IF NOT EXISTS `request_attr` (
`request_id` int(11) NOT NULL REFERENCES request(id),
`request_attr_type_id` int(11) NOT NULL REFERENCES request_attr_type(id),
`attr_value` varchar(255) NOT NULL,
PRIMARY KEY(`request_id`,`request_attr_type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `request_attr_type`;
CREATE TABLE IF NOT EXISTS `request_attr_type` (
`id` int(11) NOT NULL auto_increment,
`attr_name` varchar(255) NOT NULL,
`attr_value_regex` varchar(255) NOT NULL,
`attr_hint` TEXT default NULL,
`attr_required` tinyint(1) default 0,
`request_type_id` int(11) NOT NULL REFERENCES request_type(id),
PRIMARY KEY(`id`),
KEY `request_type_id` (`request_type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- VIEWS
--
--
-- mailer_alias view
--
CREATE OR REPLACE VIEW mailer_alias AS
SELECT CONCAT(a.alias_localpart, '@', d.domain_name), a.alias_remote
FROM mail_domain d, mail_alias a
WHERE d.id = a.mail_domain_id AND d.is_enabled = 1;
--
-- mailer_alias_adomain view
--
CREATE OR REPLACE VIEW mailer_alias_adomain AS
SELECT CONCAT(a.alias_localpart, '@', ad.alias_name) AS address, a.alias_remote
FROM mail_domain md, mail_alias_domain ad, mail_alias a
WHERE md.id = a.mail_domain_id AND md.is_enabled = 1 AND ad.mail_domain_id = md.id;
--
-- mailer_domain view
--
CREATE OR REPLACE VIEW mailer_domain AS
SELECT d.domain_name
FROM mail_domain d
WHERE d.is_enabled = 1;
--
-- mailer_alias_domain view
--
CREATE OR REPLACE VIEW mailer_alias_domain AS
SELECT a.alias_name, d.system_group_id
FROM mail_domain d, mail_alias_domain a
WHERE d.id = a.mail_domain_id AND d.is_enabled = 1;
--
-- mailer_box view
--
CREATE OR REPLACE VIEW mailer_box AS
SELECT CONCAT(mb.box_localpart, '@', md.domain_name) AS address,
su.sys_uid AS uid, sg.sys_gid AS gid,
CONCAT('/data/mail/', md.domain_name, '/', mb.box_localpart, '/') AS location,
mb.box_password AS password
FROM mail_domain md, mail_box mb, system_user su, system_group sg
WHERE mb.mail_domain_id = md.id
AND mb.system_user_id = su.id
AND md.system_group_id = sg.id
AND md.is_enabled = 1
AND mb.is_enabled = 1;
--
-- mailer_box_adomain view
--
CREATE OR REPLACE VIEW mailer_box_adomain AS
SELECT CONCAT(mb.box_localpart, '@', ad.alias_name) AS address,
su.sys_uid AS uid, sg.sys_gid AS gid,
CONCAT('/data/mail/', md.domain_name, '/', mb.box_localpart, '/') AS location,
mb.box_password AS password
FROM mail_domain md, mail_alias_domain ad, mail_box mb, system_user su, system_group sg
WHERE mb.mail_domain_id = md.id
AND mb.system_user_id = su.id
AND ad.mail_domain_id = md.id
AND md.system_group_id = sg.sys_gid
AND md.is_enabled = 1
AND mb.is_enabled = 1;
--
-- Every user gets his own database (system_<username>)
-- containing views for everything he or she may access and/or
-- modify.
-- Additionally grants are set that allow fine-grained access restrictions.
-- In the example below the user may select all fields but password
-- from the view and update all fields but the uid and the gid.
-- --> This should be perfectly sane and secure.
--
CREATE OR REPLACE VIEW system.self AS
SELECT su.id AS system_id, su.sys_uid AS uid, su.sys_username AS username,
su.email AS email, su.sys_gecos AS gecos, sg.sys_gid AS gid,
su.sys_password AS password, sg.sys_groupname AS groupname,
su.sys_shell AS shell
FROM system.system_user su, system.system_group sg
WHERE su.system_group_id = sg.id
AND su.is_enabled = 1
AND CONCAT(su.sys_username,'@localhost') = SESSION_USER()
WITH CHECK OPTION;
GRANT SELECT (system_id,uid,username,email,gecos,gid,groupname, shell)
ON system.self
TO 'sp'@'localhost';
GRANT UPDATE (username,email,gecos,groupname,password) ON system.self
TO 'sp'@'localhost';
GRANT SELECT (system_id,uid,username,email,gecos,gid,groupname,shell)
ON system.self
TO 'tester'@'localhost';
GRANT UPDATE (username,email,gecos,groupname,password) ON system.self
TO 'tester'@'localhost';
CREATE OR REPLACE VIEW system.groups AS
SELECT sg.id AS system_group_id, su.id AS system_user_id, sg.sys_gid AS gid,
su.sys_uid AS uid, sg.sys_groupname AS groupname,
sgm.group_admin AS admin
FROM system.system_user su, system.system_group sg,
system.system_group_membership sgm
WHERE sgm.system_user_id = su.id
AND sgm.system_group_id = sg.id
AND su.is_enabled = 1
AND sg.is_enabled = 1
AND CONCAT(su.sys_username, '@localhost') = SESSION_USER()
WITH CHECK OPTION;
GRANT SELECT ON system.groups TO 'sp'@'localhost';
GRANT SELECT ON system.groups TO 'tester'@'localhost';
CREATE OR REPLACE VIEW system.group_users AS
SELECT sg.id AS system_group_id, su.id AS system_user_id, sg.sys_gid AS gid,
su.sys_uid AS uid, su.sys_username AS username,
sg.sys_groupname AS groupname, sgm.group_admin AS admin
FROM system.system_user su, system.system_group sg,
system.system_group_membership sgm, system.system_user su2,
system.system_group_membership sgm2
WHERE sgm.system_user_id = su.id
AND sgm.system_group_id = sg.id
AND sgm2.system_user_id = su2.id
AND sgm2.system_group_id = sg.id
AND su.is_enabled = 1
AND su2.is_enabled = 1
AND sg.is_enabled = 1
AND CONCAT(su2.sys_username, '@localhost') = SESSION_USER()
WITH CHECK OPTION;
GRANT SELECT ON system.group_users TO 'sp'@'localhost';
GRANT SELECT ON system.group_users TO 'tester'@'localhost';
CREATE OR REPLACE VIEW system.group_users_admin AS
SELECT sg.id AS system_group_id, su.id As system_user_id,
sg.sys_gid AS gid, su.sys_uid AS uid, sgm.group_admin AS admin
FROM system.system_user su, system.system_group sg,
system.system_group_membership sgm, system.system_user su2,
system.system_group_membership sgm2
WHERE sgm.system_user_id = su.id
AND sgm.system_group_id = sg.id
AND sgm2.system_user_id = su2.id
AND sgm2.system_group_id = sg.id
AND su.is_enabled = 1
AND su2.is_enabled = 1
AND sg.is_enabled = 1
AND sgm2.group_admin = 1
AND su.id != su2.id
AND CONCAT(su2.sys_username, '@localhost') = SESSION_USER()
WITH CHECK OPTION;
GRANT SELECT, UPDATE ON system.group_users_admin TO 'sp'@'localhost';
GRANT SELECT, UPDATE ON system.group_users_admin TO 'tester'@'localhost';
CREATE OR REPLACE VIEW system.users AS
SELECT su.id AS system_user_id, su.sys_username AS username,
su.sys_uid AS uid, su.sys_gecos AS gecos, su.email AS email
FROM system.system_user su, system.system_group_membership sgm
WHERE su.id = sgm.system_user_id
AND sgm.system_group_id IN
(SELECT ssg.id
FROM system.system_group ssg, system.system_group_membership ssgm,
system.system_user ssu
WHERE ssu.id = ssgm.system_user_id
AND ssg.id = ssgm.system_group_id
AND CONCAT(ssu.sys_username, '@localhost') = SESSION_USER())
WITH CHECK OPTION;
GRANT SELECT ON system.users TO 'sp'@'localhost';
GRANT SELECT ON system.users TO 'tester'@'localhost';
CREATE OR REPLACE VIEW system.all_users AS
SELECT su.id AS system_user_id, su.sys_username AS username,
su.sys_uid AS uid, su.sys_gecos AS gecos
FROM system.system_user su
ORDER BY system_user_id;
GRANT SELECT ON system.all_users TO 'sp'@'localhost';
GRANT SELECT ON system.all_users TO 'tester'@'localhost';
CREATE OR REPLACE VIEW system.requests AS
SELECT r.id, r.system_user_id, r.request_type_id, r.activated, r.done,
r.timestamp
FROM system.request r, system_user su
WHERE r.system_user_id = su.id
AND CONCAT(su.sys_username,'@localhost') = SESSION_USER()
WITH CHECK OPTION;
GRANT SELECT,INSERT ON system.requests TO 'sp'@'localhost';
GRANT SELECT,INSERT ON system.requests TO 'tester'@'localhost';
--
-- don't ask me why, but we should be adding a 'null' request for all users
--
--INSERT INTO system.request (system_user_id, request_type_id, done, timestamp)
-- VALUES(1,0,1,0);
--INSERT INTO system.request (system_user_id, request_type_id, done, timestamp)
-- VALUES(2,0,1,0);
--
-- now set user passwords
--
GRANT USAGE ON *.* TO 'sp'@'localhost' IDENTIFIED BY 'sp';
GRANT USAGE ON *.* TO 'tester'@'localhost' IDENTIFIED BY 'tester';
--
-- Table data
--
INSERT INTO `mail_admin_user` (`id`, `mail_domain_id`, `system_user_id`, `timestamp`) VALUES
(1, 1, 1, '2007-04-07 22:59:44');
INSERT INTO `mail_box` (`id`, `box_localpart`, `is_enabled`, `box_password`, `timestamp`, `mail_domain_id`, `system_user_id`) VALUES
(1, 'tester', 1, 'test', '2007-04-07 22:55:37', 1, 1);
--
-- Dumping data for table `mail_domain`
--
INSERT INTO `mail_domain` (`id`, `domain_name`, `is_enabled`, `system_group_id`, `timestamp`) VALUES
(1, 'test.example.org', 1, 1, '2007-04-07 22:50:44');
--
-- Dumping data for table `system_group`
--
INSERT INTO `system_group` (`id`, `sys_gid`, `sys_groupname`, `is_enabled`, `timestamp`) VALUES
(1, 8000, 'mail-0', 1, '2007-04-07 21:53:11'),
(2, 8001, 'mail-1', 1, '2007-04-07 21:53:11'),
(3, 2000, 'sp', 1, '2007-04-07 21:53:36'),
(4, 5000, 'web-0', 1, '2007-04-07 21:53:54'),
(5, 2001, 'tester', 1, '2007-04-08 11:10:11');
--
-- Dumping data for table `system_group_membership`
--
INSERT INTO `system_group_membership` (`id`, `system_group_id`, `system_user_id`, `timestamp`, `group_admin`) VALUES
(1, 3, 1, '2007-04-08 11:09:30', 1),
(2, 3, 2, '2007-04-08 12:09:59', 0);
--
-- Dumping data for table `system_user`
--
INSERT INTO `system_user` (`id`, `sys_uid`, `sys_username`, `email`, `system_group_id`, `sys_password`, `is_enabled`, `sys_gecos`, `timestamp`) VALUES
(1, 2000, 'sp', 'sp@example.org', 3, '1952a01898073d1e561b9b4f2e42cbd7', 1, 'Stephan Peijnik', '2007-04-08 00:00:52'),
(2, 2001, 'tester', 'tester@test.example.org', 5, 'f5d1278e8109edd94e1e4197e04873b9', 1, 'Test user', '2007-04-08 11:39:20');
--
-- Dumping data for table `web_site`
--
INSERT INTO `web_site` (`id`, `site_name`, `site_admin_email`, `is_enabled`, `timestamp`, `system_group_id`) VALUES
(1, 'test.example.org', 'tester@test.example.org', 1, '2007-04-07 23:00:42', 4);
--
-- Dumping data for table `web_site_alias`
--
--
-- Dumping data for table `web_site_user`
--