Zugriffsverwaltung (CMS)
Im CMS ContentLion gibt es bereits Rolle die gewisse Einstellungen haben. Dort machen wir heute etwas ganz wichtiges: Die Zugriffsverwaltung. Die Rechte selbst werden beim Seite-Bearbeiten vergeben. Hier kann man einfach in einer ComboBox auswählen, welchen Usern Zugriff auf die geöffnete Seite gewährt wird.
Für die Zugriffsregelung gibt es die neue Tabelle cms_role_rights:
PRIMARY KEY (`role`,`page`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Steht eine Rolle mit einer Seitenid in dieser Tabelle ist der Zugriff erlaubt. Diese schöne Tabelle muss selbstverständlich noch in den Installer. Das machen wir aber am Ende des Beitrags, weil wir dort noch etwas ändern müssen.
Zentraler Punkt der Zugriffsverwaltung ist die Klasse /system/classes/role.php. Diese ist nun mit 4 neuen Methoden ausgestattet worden. Man kann zum Beispiel mit der Funktion getAllRolls alle Rollen zurückbekommen – Das benötigen wir gleich zur Auflistung der Rollen. Bei der Funktion canAccess wird ein Page-Objekt übergeben, zurück kommt ein Boolean-Wert der angibt, ob die Seite betreten werden darf oder nicht. Die Funktion clearAccess verweigert den Zugriff für alle User und die Funktion allowAccess erlaubt den Zugriff:
<?PHP class Role{ public $name = ""; public $ID = -1; public function load($id){ $id = $GLOBALS['db']->EscapeString($id); $role = $GLOBALS['db']->ReadRow("SELECT * FROM {'dbprefix'}roles WHERE id = '".$id."'"); if($role){ $this->name = $role->name; $this->ID = $role->id; } } public function getAllRolls(){ $roles = $GLOBALS['db']->ReadRows("SELECT id FROM {'dbprefix'}roles ORDER BY name"); foreach($roles as $role){ $newRole = new Role(); $newRole->load($role->id); $res[] = $newRole; } return $res; } public function canAccess($page){ $id = $GLOBALS['db']->EscapeString($this->ID); $pageid = $GLOBALS['db']->EscapeString($page->id); return $GLOBALS['db']->ReadField("SELECT COUNT(*) FROM {'dbprefix'}role_rights WHERE role = '".$id."' AND page = '".$pageid."'") > 0; } public function clearAccess($page){ $pageid = $GLOBALS['db']->EscapeString($page->id); return $GLOBALS['db']->Execute("DELETE FROM {'dbprefix'}role_rights WHERE page = '".$pageid."'"); } public function allowAccess($page){ $id = $GLOBALS['db']->EscapeString($this->ID); $pageid = $GLOBALS['db']->EscapeString($page->id); return $GLOBALS['db']->Execute("INSERT INTO {'dbprefix'}role_rights (role,page) VALUES('".$id."','".$pageid."')"); } } ?>
Die Klasse /system/classes/page.php bekommt nun eine Methode zum Laden über die Id und nicht über den Alias -> brauchen wir später noch:
<?PHP class Page{ public $id = -1; public $alias = ""; public $title = ""; public $ownerid = -1; public $owner = false; public $menu = -1; public $meta = null; public $editor = null; function loadProperties($alias){ if ($alias == "") { $alias = "home"; } $row = $GLOBALS['db']->ReadRow("SELECT * FROM {'dbprefix'}pages WHERE alias = '".$alias."'"); $this->load($row); } function loadPropertiesById($id){ $row = $GLOBALS['db']->ReadRow("SELECT * FROM {'dbprefix'}pages WHERE id = '".$id."'"); $this->load($row); } function load($data){ if($data){ $this->id = $data->id; $this->title = $data->title; $this->ownerid = $data->owner; $this->menu = $data->menu; $this->alias = $data->alias; $this->meta = new Meta(); $this->meta->pageid = $this->id; $this->meta->load(); $this->editor = new $data->editor(); $this->editor->page = $this; } } function getContent(){ EventManager::raiseEvent("content_top",".",$this); $this->editor->display(); EventManager::raiseEvent("content_bottom",".",$this); } function getOwner(){ if(!$this->owner){ $alias = $GLOBALS['db']->ReadField("SELECT alias FROM {'dbprefix'}pages WHERE id = ".$this->ownerid."'"); if($alias){ $this->owner = new Page(); $this->owner->loadProperties($alias); } } return $this->owner; } function getBreadcrump(){ if(!$this->owner) $this->getOwner(); if($this->owner){ $breadcrump = $this->owner->getBreadcrump(); } $breadcrump[] = array($this->alias,$this->title); return $breadcrump; } function save(){ $res = $GLOBALS['db']->Execute("UPDATE {'dbprefix'}pages SET title = '".$this->title."', alias = '".$this->alias."', menu='".$this->menu."' WHERE id = '".$this->id."'"); $this->meta->save(); if($res){ $args['title'] = $this->title; $args['alias'] = $this->alias; $args['menu'] = $this->menu; $args['id'] = $this->id; EventManager::raiseEvent("page_saved","../",$args); } return $res; } function create($dirpraefix,$alias,$editor){ $res = $GLOBALS['db']->Execute("INSERT INTO {'dbprefix'}pages (alias,editor) VALUES ('".$alias."','".$editor."')"); if($res){ $args['id'] = $GLOBALS['db']->InsertID(); $args['editor'] = $editor; $args['alias'] = $alias; EventManager::raiseEvent("page_created","../",$args); } return $GLOBALS['db']->InsertID(); } function delete(){ $res = $GLOBALS['db']->Execute("DELETE FROM {'dbprefix'}pages WHERE alias = '".$this->alias."'"); if($res){ $args['alias'] = $this->alias; EventManager::raiseEvent("page_deleted","../",$args); } return $res; } function getPagesTypes(){ return $GLOBALS['db']->ReadRows("SELECT * FROM {'dbprefix'}pagetypes"); } } ?>
In der Datei /admin/includes/site-edit.php werden nun die Rechte angezeigt. Wählt man bestimmte Rollen aus, wird der Zugriff gewährt:
<?PHP $page = new Page(); $page->loadProperties($GLOBALS['db']->EscapeString($_GET['site'])); if($_POST['save']){ $oldpage = $page; $page->title = $_POST['title']; $page->menu = $_POST['menu']; $page->meta->description = $_POST['meta-description']; $page->meta->keywords = $_POST['meta-keywords']; $page->meta->robots = $_POST['meta-robots']; $page->alias = $_POST['alias']; $page->save(); $page->editor->save($page,$oldpage); Role::clearAccess($page); if($_POST['rights']){ foreach($_POST['rights'] as $right){ $role = new Role(); $role->load($right); $role->allowAccess($page); } } } else if(isset($_POST['menu'])){ $page->title = $_POST['title']; $page->alias = $_POST['alias']; $page->menu = $_POST['menu']; $page->editor->content = $_POST['content']; } ?> <h1>Seite bearbeiten</h1> <form name="form" action="/admin/index.php?page=site-edit&site=<?PHP echo $page->alias; ?>" method="post"> <div style="float:right;width:20%;"> <label for="alias">Alias:</label> <input name="alias" value="<?PHP echo $page->alias; ?>" /><br /> <h2>Rechte</h2> <select name="rights[]" size="4" multiple="yes" style="width:150px;"> <?PHP if(!isset($_POST['menu'])){ foreach(Role::getAllRolls() as $role){ if($role->canAccess($page)){ echo "<option selected="1" value="".$role->ID."">".$role->name."</option>"; } else{ echo "<option value="".$role->ID."">".$role->name."</option>"; } } } else{ foreach(Role::getAllRolls() as $role){ if(in_array($role->ID,$_POST['rights'])){ echo "<option selected="1" value="".$role->ID."">".$role->name."</option>"; } else{ echo "<option value="".$role->ID."">".$role->name."</option>"; } } } ?> </select> <h2>Seitenmenü</h2> <select name="menu" onchange="document.form.submit();"> <option value="0">– Kein Menü –</option> <?PHP foreach(sys::getMenues() as $menue){ echo "<option value="".$menue->id."""; if($_POST['menu'] == $menue->id){ echo " selected="selected""; } else if($page->menu == $menue->id && !$_POST['menu']){ echo " selected="selected""; } echo ">".$menue->name."</option>"; } ?> </select> <div id="menupreview"> <?PHP if($_POST['menu']){ Menu::display($_POST['menu'],"<ul>","</ul>","<li>","</li>",""); } else if($page->menu > 0){ Menu::display($page->menu,"<ul>","</ul>","<li>","</li>",""); } ?> </div> <h2>Meta Daten</h2> <label for="meta-description">Description:</label> <input name="meta-description" value="<?PHP echo $page->meta->description; ?>" /><br /> <label for="meta-keywords">Keywords:</label> <input name="meta-keywords" value="<?PHP echo $page->meta->keywords; ?>" /><br /> <label for="meta-robots">Robots:</label> <input name="meta-robots" value="<?PHP echo $page->meta->robots; ?>" /><br /> </div> <div> <input name="title" value="<?PHP echo $page->title; ?>" style="width:70%;height:25px;margin-bottom:5px;font-size:20px;" /><br /> <?PHP $page->editor->displayEditable(); ?> </div> </form>
Wir brauche noch eine Seite, die angezeigt wird, wenn der Zugriff verweigert wurde. Diese wird über den Setting accessdenied gesetzt:
INSERT INTO `cms_settings` VALUES (3, ‚global‘, ‚global‘, ‚accessdenied‘, ’39‘, 1, ‚Zugriff-Verweigert-Seite‘, ‚pageselector‘);
In der /index.php wird nun geprüft, ob der Zugriff erlaubt ist:
function __autoload($class_name){
$namespaces = split(„_“,strtolower($class_name));
if(sizeOf($namespaces) == 3){
if($namespaces[0] == „plugin“){
require_once „system/plugins/“.$namespaces[1].„/classes/“.$namespaces[2].„.php“;
$imported = true;
}
else if($namespaces[0] == „skin“){
require_once „system/skins/“.$namespaces[1].„/classes/“.$namespaces[2].„.php“;
$imported = true;
}
}
if(!$imported){
require_once „system/classes/“.strtolower($class_name).„.php“;
}
}
include(„system/settings.php“);
include(„system/filterfilename.php“);
include(„system/sys.php“);
$db = new MySQL(’system/dbsettings.php‘);
$db->Connect();
if(!isset($_SESSION[‚user‘])) $_SESSION[‚user‘] = new User();
$currentpage = new Page();
$currentpage->loadProperties($GLOBALS[‚db‘]->EscapeString($_GET[‚include‘]));
if(!$_SESSION[‚user‘]->role->canAccess($currentpage)){
$currentpage = new Page();
$currentpage->loadPropertiesById(getSetting(„global“,„global“,„accessdenied“));
}
if(!$_GET[’skin‘]){
include(SkinController::getCurrentSkinPath().„/index.php“);
}
else{
include(’system/skins/‘.$_GET[’skin‘].„/index.php“);
}
?>
Fehlt nur noch der /installer/installer.php:
private function createTables(){
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„activated_plugins` ();
`path` varchar(100) NOT NULL,
PRIMARY KEY (`path`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„custom_css` ();
`id` varchar(100) NOT NULL,
`stylePath` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„dashboards` ();
`id` int(10) NOT NULL,
`col` int(1) NOT NULL,
`row` int(2) NOT NULL,
`path` varchar(255) NOT NULL,
PRIMARY KEY (`id`,`col`,`row`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„events` ();
`event` varchar(50) NOT NULL,
`file` varchar(50) NOT NULL,
PRIMARY KEY (`event`,`file`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„images` ();
`path` varchar(255) NOT NULL,
`name` varchar(75) NOT NULL,
`description` varchar(255) NOT NULL,
PRIMARY KEY (`path`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„menu` ();
`id` int(2) NOT NULL,
`menuID` int(3) NOT NULL,
`title` varchar(100) NOT NULL,
`href` varchar(255) NOT NULL,
`type` int(1) NOT NULL,
PRIMARY KEY (`id`,`menuID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„menu_names` ();
`id` int(4) NOT NULL auto_increment,
`name` varchar(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=17 DEFAULT CHARSET=utf8 AUTO_INCREMENT=17 ;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„meta_global` ();
`name` varchar(100) NOT NULL,
`content` varchar(100) NOT NULL,
PRIMARY KEY (`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„meta_local` ();
`name` varchar(100) NOT NULL,
`page` int(11) NOT NULL,
`content` varchar(100) NOT NULL,
PRIMARY KEY (`name`,`page`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„pages` ();
`id` int(8) NOT NULL auto_increment,
`alias` varchar(255) NOT NULL,
`title` varchar(255) NOT NULL,
`owner` int(11) NOT NULL default ‚-1‘,
`menu` int(11) NOT NULL default ‚-1‘,
`editor` varchar(50) NOT NULL default ‚WYSIWYG‘,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=35 DEFAULT CHARSET=utf8 AUTO_INCREMENT=35 ;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„settings` ();
`role` int(10) NOT NULL default ‚3‘,
`area` varchar(20) NOT NULL,
`areaType` varchar(20) NOT NULL,
`property` varchar(255) NOT NULL,
`value` varchar(255) NOT NULL,
`activated` int(1) NOT NULL default ‚1‘,
`description` varchar(75) NOT NULL,
`type` varchar(50) NOT NULL,
PRIMARY KEY (`role`,`area`,`areaType`,`property`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„skins` ();
`id` int(3) NOT NULL auto_increment,
`name` varchar(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„user` ();
`id` int(11) NOT NULL auto_increment,
`name` varchar(50) NOT NULL,
`password` varchar(50) NOT NULL,
`role` int(10) NOT NULL,
PRIMARY KEY (`id`,`name`)
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„widgets` ();
`path` varchar(255) NOT NULL,
`name` varchar(50) NOT NULL,
`class` varchar(50) NOT NULL,
PRIMARY KEY (`path`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„roles` ();
`id` int(10) NOT NULL auto_increment,
`name` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;“
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„pagetypes` ();
`id` INT( 10 ) NOT NULL AUTO_INCREMENT ,
`class` VARCHAR( 50 ) NOT NULL ,
`name` VARCHAR( 50 ) NOT NULL ,
PRIMARY KEY ( `id` ) ) TYPE = MYISAM ;“
}
mysql_query(„CREATE TABLE `“.$this->params[3][‚praefix‘].„role_rights` ();
`role` int(10) NOT NULL,
`page` int(10) NOT NULL,
PRIMARY KEY (`role`,`page`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;“
}
private function insertRows(){
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„menu_names` VALUES (1, ‚{admin}‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„menu` VALUES (1, 1, ‚Dashboard‘, ‚/admin/‘,1;“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„menu` VALUES (2, 1, ‚Seiten‘, ‚/admin/index.php?page=sites‘,1);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„menu` VALUES (3, 1, ‚Menüs‘, ‚/admin/index.php?page=menues‘,1);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„menu` VALUES (4, 1, ‚Dateien‘, ‚/admin/index.php?page=files‘,1);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„menu` VALUES (5, 1, ‚Plugins‘, ‚/admin/index.php?page=plugins‘,1);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„menu` VALUES (7, 1, ‚Einstellungen‘, ‚/admin/index.php?page=settings‘,1);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„menu` VALUES (8, 1, ‚Benutzer‘, ‚/admin/index.php?page=user‘,1);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„menu` VALUES (9, 1, ‚Logout‘, ‚/admin/index.php?page=logout‘,1);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„user` VALUES (1, ‚“.$this->params[4][‚user‘].„‚, ‚“.md5($this->params[4][‚password‘]).„‚,2);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„settings` VALUES (3,’global‘, ‚global‘, ‚title‘, ‚“.$this->params[4][’name‘].„‚, 1, ‚Titel des CMS‘,’textbox‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„settings` VALUES (3,’global‘, ‚global‘, ’selectedskin‘, ‚1‘, 1, ‚Aktueller Skin‘,’skinselector‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„settings` VALUES (3,’global‘, ‚global‘, ’selectedmobileskin‘, ‚1‘, 1, ‚Mobiler Skin‘,’mobileskinselector‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„settings` VALUES (3,’default‘, ’skins‘, ’skinbgcolor‘, ‚dedede‘, 1, ‚Hintergrundfarbe‘,’colorpicker‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„settings` VALUES (3,’default‘, ’skins‘, ’skinforecolor‘, ‚525252‘, 1, ‚Schriftfarbe‘,’colorpicker‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„settings` VALUES (3,’default‘, ’skins‘, ’skinhighlight1′, ‚ff0000‘, 1, ‚Highlight Farbe 1′,’colorpicker‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„settings` VALUES (3,’default‘, ’skins‘, ’skinhighlight2′, ‚b3fa00‘, 1, ‚Highlight Farbe 2′,’colorpicker‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„settings` VALUES (3,’global‘, ‚global‘, ‚host‘, ‚http://“.$_SERVER[‚HTTP_HOST‘].„‚, 1, ‚URL der Startseite‘,’textbox‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„settings` VALUES (3, ‚global‘, ‚global‘, ‚mainmenu‘, ‚4‘, 0, ‚Hauptmenü‘, ‚menueselector‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„settings` VALUES (2, ‚global‘, ‚global‘, ‚mainmenu‘, ‚4‘, 1, ‚Hauptmenü‘, ‚menueselector‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„settings` VALUES (2, ‚global‘, ‚global‘, ‚‘accessdenied’‘, ‚0‘, 1, ‚Zugriff-Verweigert-Seite‘, ‚‘pageselector’‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„skins` VALUES (1, ‚default‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„skins` VALUES (2, ‚mobile‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„roles` VALUES (1, ‚Gast‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„roles` VALUES (2, ‚Administator‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„roles` VALUES (3, ‚Alle‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„pagetypes` VALUES (1, ‚wysiwyg‘, ‚Textseite‘);“);
mysql_query(„INSERT INTO `“.$this->params[3][‚praefix‘].„pagetypes` VALUES (2, ‚login‘, ‚Login‘);“);
}
Die Zugriff-Verweigert Seite wird wahrscheinlich noch nicht passen – wir brauchen erst noch vernünftige Beispieldaten. Morgen oder übermorgen wird wahrscheinlich mein Headset ankommen – Dann können wir bald mit unserer Live_programmierung anfangen. Ich werde in Kürze auch einen Zeitplan veröffentlichen, in dem dann auch der Termin für den Alpha-Release spowie der Termin für die Live-Programmierung drin stehen.
Du arbeitest in einer Agentur oder als Freelancer?
Dann wirf doch mal einen Blick auf unsere Software FeatValue.
Kommentare
Daniel schrieb am 07.05.2010:
Ich würde die Rechteverwaltung auch auf die übrigen Adminmenüpunkte ausweiten. Demnach müsste jemand der Dateien hoch laden will auch das Recht dazu haben usw.
Stefan Wienströer schrieb am 07.05.2010:
Genau das hab ich vor ;-)
Daniel schrieb am 07.05.2010:
Ups. Entschuldigung das ic Dir da vorgegriffen habe. ^^
Stefan Wienströer schrieb am 07.05.2010:
Kein Thema^^ Bestätigt nur, dass ich mit meiner / deiner Idee nicht verkehrt liege
Über uns
Wir entwickeln Webanwendungen mit viel Leidenschaft. Unser Wissen geben wir dabei gerne weiter. Mehr über a coding project