diff options
76 files changed, 1406 insertions, 654 deletions
diff --git a/lib/gallery.common.css b/lib/gallery.common.css index 77653d00..2a8eddb2 100644 --- a/lib/gallery.common.css +++ b/lib/gallery.common.css @@ -2,7 +2,7 @@ * Gallery 3 commonly re-used screen styles * * Sheet organization: - * + * * 1) Text * 2) Forms * 3) Dimension and scale @@ -219,7 +219,7 @@ li.g-error select { margin-bottom: .2em; } -.g-error, +.g-error, .g-denied, tr.g-error td.g-error { background: #f6cbca url('images/ico-error.png') no-repeat .4em 50%; @@ -235,7 +235,7 @@ tr.g-error td.g-error { background: #d9efc2 url('images/ico-success.png') no-repeat .4em 50%; } -.g-warning, +.g-warning, tr.g-warning td.g-warning { background: #fcf9ce url('images/ico-warning.png') no-repeat .4em 50%; } diff --git a/modules/akismet/tests/Akismet_Helper_Test.php b/modules/akismet/tests/Akismet_Helper_Test.php index d001d3ad..6788e7a3 100644 --- a/modules/akismet/tests/Akismet_Helper_Test.php +++ b/modules/akismet/tests/Akismet_Helper_Test.php @@ -26,7 +26,7 @@ class Akismet_Helper_Test extends Unit_Test_Case { $root = ORM::factory("item", 1); $this->_comment = comment::create( - $root, user::guest(), "This is a comment", + $root, Identity::guest(), "This is a comment", "John Doe", "john@gallery2.org", "http://gallery2.org"); foreach ($this->_comment->list_fields("comments") as $name => $field) { if (strpos($name, "server_") === 0) { diff --git a/modules/comment/controllers/comments.php b/modules/comment/controllers/comments.php index 82b12893..c0658cc1 100644 --- a/modules/comment/controllers/comments.php +++ b/modules/comment/controllers/comments.php @@ -65,7 +65,7 @@ class Comments_Controller extends REST_Controller { $form = comment::get_add_form($item); $valid = $form->validate(); if ($valid) { - if (user::active()->guest && !$form->add_comment->inputs["name"]->value) { + if (Session::active_user()->guest && !$form->add_comment->inputs["name"]->value) { $form->add_comment->inputs["name"]->add_error("missing", 1); $valid = false; } @@ -78,13 +78,13 @@ class Comments_Controller extends REST_Controller { if ($valid) { $comment = comment::create( - $item, user::active(), + $item, Session::active_user(), $form->add_comment->text->value, $form->add_comment->inputs["name"]->value, $form->add_comment->email->value, $form->add_comment->url->value); - $active = user::active(); + $active = Session::active_user(); if ($active->guest) { $form->add_comment->inputs["name"]->value(""); $form->add_comment->email->value(""); @@ -192,7 +192,7 @@ class Comments_Controller extends REST_Controller { * @see REST_Controller::form_edit($resource) */ public function _form_edit($comment) { - if (!user::active()->admin) { + if (!Session::active_user()->admin) { access::forbidden(); } print comment::get_edit_form($comment); diff --git a/modules/comment/helpers/comment.php b/modules/comment/helpers/comment.php index 7b2332a8..e741266d 100644 --- a/modules/comment/helpers/comment.php +++ b/modules/comment/helpers/comment.php @@ -75,7 +75,7 @@ class comment_Core { module::event("comment_add_form", $form); $group->submit("")->value(t("Add")); - $active = user::active(); + $active = Session::active_user(); if (!$active->guest) { $group->inputs["name"]->value($active->full_name)->disabled("disabled"); $group->email->value($active->email)->disabled("disabled"); diff --git a/modules/comment/models/comment.php b/modules/comment/models/comment.php index de9b0cd6..5e29e778 100644 --- a/modules/comment/models/comment.php +++ b/modules/comment/models/comment.php @@ -23,7 +23,7 @@ class Comment_Model extends ORM { } function author() { - return user::lookup($this->author_id); + return Identity::lookup_user($this->author_id); } function author_name() { diff --git a/modules/comment/tests/Comment_Event_Test.php b/modules/comment/tests/Comment_Event_Test.php index c51c65c9..eb301893 100644 --- a/modules/comment/tests/Comment_Event_Test.php +++ b/modules/comment/tests/Comment_Event_Test.php @@ -22,7 +22,7 @@ class Comment_Event_Test extends Unit_Test_Case { $rand = rand(); $album = album::create(ORM::factory("item", 1), "test_$rand", "test_$rand"); $comment = comment::create( - $album, user::guest(), "text_$rand", "name_$rand", "email_$rand", "url_$rand"); + $album, Identity::guest(), "text_$rand", "name_$rand", "email_$rand", "url_$rand"); $album->delete(); diff --git a/modules/comment/tests/Comment_Helper_Test.php b/modules/comment/tests/Comment_Helper_Test.php index f84fe0f9..e8ab7c79 100644 --- a/modules/comment/tests/Comment_Helper_Test.php +++ b/modules/comment/tests/Comment_Helper_Test.php @@ -48,7 +48,7 @@ class Comment_Helper_Test extends Unit_Test_Case { $rand = rand(); $root = ORM::factory("item", 1); $comment = comment::create( - $root, user::guest(), "text_$rand", "name_$rand", "email_$rand", "url_$rand"); + $root, Identity::guest(), "text_$rand", "name_$rand", "email_$rand", "url_$rand"); $this->assert_equal("name_$rand", $comment->author_name()); $this->assert_equal("email_$rand", $comment->author_email()); @@ -77,7 +77,7 @@ class Comment_Helper_Test extends Unit_Test_Case { public function create_comment_for_user_test() { $rand = rand(); $root = ORM::factory("item", 1); - $admin = user::lookup(2); + $admin = Identity::lookup_user(2); $comment = comment::create( $root, $admin, "text_$rand", "name_$rand", "email_$rand", "url_$rand"); diff --git a/modules/comment/tests/Comment_Model_Test.php b/modules/comment/tests/Comment_Model_Test.php index f4c68b15..84532a96 100644 --- a/modules/comment/tests/Comment_Model_Test.php +++ b/modules/comment/tests/Comment_Model_Test.php @@ -22,17 +22,17 @@ class Comment_Model_Test extends Unit_Test_Case { public function cant_view_comments_for_unviewable_items_test() { $root = ORM::factory("item", 1); $album = album::create($root, rand(), rand(), rand()); - $comment = comment::create($album, user::guest(), "text", "name", "email", "url"); - user::set_active(user::guest()); + $comment = comment::create($album, Identity::guest(), "text", "name", "email", "url"); + Session::set_active_user(Identity::guest()); // We can see the comment when permissions are granted on the album - access::allow(group::everybody(), "view", $album); + access::allow(Identity::everybody(), "view", $album); $this->assert_equal( 1, ORM::factory("comment")->viewable()->where("comments.id", $comment->id)->count_all()); // We can't see the comment when permissions are denied on the album - access::deny(group::everybody(), "view", $album); + access::deny(Identity::everybody(), "view", $album); $this->assert_equal( 0, ORM::factory("comment")->viewable()->where("comments.id", $comment->id)->count_all()); diff --git a/modules/digibug/controllers/digibug.php b/modules/digibug/controllers/digibug.php index 0939704b..8ea83601 100644 --- a/modules/digibug/controllers/digibug.php +++ b/modules/digibug/controllers/digibug.php @@ -23,7 +23,7 @@ class Digibug_Controller extends Controller { $item = ORM::factory("item", $id); access::required("view", $item); - if (access::group_can(group::everybody(), "view_full", $item)) { + if (access::group_can(Identity::everybody(), "view_full", $item)) { $full_url = $item->file_url(true); $thumb_url = $item->thumb_url(true); } else { diff --git a/modules/digibug/tests/Digibug_Controller_Test.php b/modules/digibug/tests/Digibug_Controller_Test.php index 859ff637..19f57972 100644 --- a/modules/digibug/tests/Digibug_Controller_Test.php +++ b/modules/digibug/tests/Digibug_Controller_Test.php @@ -35,8 +35,8 @@ class Digibug_Controller_Test extends Unit_Test_Case { $root = ORM::factory("item", 1); $this->_album = album::create($root, rand(), "test album"); - access::deny(group::everybody(), "view_full", $this->_album); - access::deny(group::registered_users(), "view_full", $this->_album); + access::deny(Identity::everybody(), "view_full", $this->_album); + access::deny(Identity::registered_users(), "view_full", $this->_album); $rand = rand(); $this->_item = photo::create($this->_album, MODPATH . "gallery/tests/test.jpg", "$rand.jpg", diff --git a/modules/g2_import/helpers/g2_import.php b/modules/g2_import/helpers/g2_import.php index 7e5c6f75..d24aab93 100644 --- a/modules/g2_import/helpers/g2_import.php +++ b/modules/g2_import/helpers/g2_import.php @@ -230,16 +230,16 @@ class g2_import_Core { switch ($g2_group->getGroupType()) { case GROUP_NORMAL: try { - $group = group::create($g2_group->getGroupName()); + $group = Identity::create_group($g2_group->getGroupName()); } catch (Exception $e) { // @todo For now we assume this is a "duplicate group" exception - $group = group::lookup_by_name($g2_group->getGroupname()); + $group = Identity::lookup_user_by_name($g2_group->getGroupname()); } $message = t("Group '%name' was imported", array("name" => $g2_group->getGroupname())); break; case GROUP_ALL_USERS: - $group = group::registered_users(); + $group = Identity::registered_users(); $message = t("Group 'Registered' was converted to '%name'", array("name" => $group->name)); break; @@ -248,7 +248,7 @@ class g2_import_Core { break; // This is not a group in G3 case GROUP_EVERYBODY: - $group = group::everybody(); + $group = Identity::everybody(); $message = t("Group 'Everybody' was converted to '%name'", array("name" => $group->name)); break; } @@ -270,7 +270,7 @@ class g2_import_Core { } if (g2(GalleryCoreApi::isAnonymousUser($g2_user_id))) { - self::set_map($g2_user_id, user::guest()->id); + self::set_map($g2_user_id, Identity::guest()->id); return t("Skipping Anonymous User"); } @@ -285,11 +285,11 @@ class g2_import_Core { $g2_groups = g2(GalleryCoreApi::fetchGroupsForUser($g2_user->getId())); try { - $user = user::create($g2_user->getUsername(), $g2_user->getfullname(), ""); + $user = Identity::create_user($g2_user->getUsername(), $g2_user->getfullname(), ""); $message = t("Created user: '%name'.", array("name" => $user->name)); } catch (Exception $e) { // @todo For now we assume this is a "duplicate user" exception - $user = user::lookup_by_name($g2_user->getUsername()); + $user = Identity::lookup_user_by_name($g2_user->getUsername()); $message = t("Loaded existing user: '%name'.", array("name" => $user->name)); } @@ -301,7 +301,7 @@ class g2_import_Core { $user->admin = true; $message .= t("\n\tAdded 'admin' flag to user"); } else { - $group = ORM::factory("group", self::map($g2_group_id)); + $group = Identity::lookup_group(self::map($g2_group_id)); $user->add($group); $message .= t("\n\tAdded user to group '%group'.", array("group" => $group->name)); } @@ -313,7 +313,6 @@ class g2_import_Core { return $message; } - /** * Import a single album. */ diff --git a/modules/gallery/controllers/admin.php b/modules/gallery/controllers/admin.php index b92a32cd..24eebe7d 100644 --- a/modules/gallery/controllers/admin.php +++ b/modules/gallery/controllers/admin.php @@ -21,7 +21,7 @@ class Admin_Controller extends Controller { private $theme; public function __construct($theme=null) { - if (!(user::active()->admin)) { + if (!(Session::active_user()->admin)) { access::forbidden(); } diff --git a/modules/gallery/controllers/admin_identity.php b/modules/gallery/controllers/admin_identity.php new file mode 100644 index 00000000..9d756a5c --- /dev/null +++ b/modules/gallery/controllers/admin_identity.php @@ -0,0 +1,75 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2009 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +class Admin_Identity_Controller extends Admin_Controller { + public function index() { + $view = new Admin_View("admin.html"); + $view->content = new View("admin_identity.html"); + $view->content->available = Identity::providers(); + $view->content->active = module::get_var("gallery", "identity_provider", "user"); + print $view; + } + + public function confirm() { + access::verify_csrf(); + + $v = new View("admin_identity_confirm.html"); + $v->new_provider = $this->input->post("provider"); + + print $v; + } + + public function change() { + access::verify_csrf(); + + $active_provider = module::get_var("gallery", "identity_provider", "user"); + $providers = Identity::providers(); + + $new_provider = $this->input->post("provider"); + + if ($new_provider != $active_provider) { + + module::event("pre_identity_change", $active_provider, $new_provider); + + Identity::deactivate(); + + // Switch authentication + module::set_var("gallery", "identity_provider", $new_provider); + Identity::reset(); + + Identity::activate(); + + // @todo this type of collation is questionable from an i18n perspective + message::success(t("Changed to %description", + array("description" => $providers->$new_provider))); + + try { + Session::instance()->destroy(); + } catch (Exception $e) { + // We don't care if there was a problem destroying the session. + } + url::redirect(item::root()->abs_url()); + } + + message::info(t("The selected provider \"%description\" is already active.", + array("description" => $providers->$new_provider))); + url::redirect("admin/identity"); + } +} + diff --git a/modules/gallery/controllers/albums.php b/modules/gallery/controllers/albums.php index ae4ad395..9480a037 100644 --- a/modules/gallery/controllers/albums.php +++ b/modules/gallery/controllers/albums.php @@ -29,7 +29,7 @@ class Albums_Controller extends Items_Controller { $view = new Theme_View("page.html", "login"); $view->page_title = t("Log in to Gallery"); $view->content = new View("login_ajax.html"); - $view->content->form = user::get_login_form("login/auth_html"); + $view->content->form = login::get_login_form("login/auth_html"); print $view; return; } else { @@ -111,7 +111,7 @@ class Albums_Controller extends Items_Controller { $this->input->post("name"), $this->input->post("title", $this->input->post("name")), $this->input->post("description"), - user::active()->id, + Session::active_user()->id, $this->input->post("slug")); log::success("content", "Created an album", @@ -146,7 +146,7 @@ class Albums_Controller extends Items_Controller { $_FILES["file"]["name"], $this->input->post("title", $this->input->post("name")), $this->input->post("description"), - user::active()->id); + Session::active_user()->id); log::success("content", "Added a photo", html::anchor("photos/$photo->id", "view photo")); message::success(t("Added photo %photo_title", diff --git a/modules/gallery/controllers/l10n_client.php b/modules/gallery/controllers/l10n_client.php index 6fdbb3a1..2ab73102 100644 --- a/modules/gallery/controllers/l10n_client.php +++ b/modules/gallery/controllers/l10n_client.php @@ -20,7 +20,7 @@ class L10n_Client_Controller extends Controller { public function save() { access::verify_csrf(); - if (!user::active()->admin) { + if (!Session::active_user()->admin) { access::forbidden(); } @@ -85,7 +85,7 @@ class L10n_Client_Controller extends Controller { public function toggle_l10n_mode() { access::verify_csrf(); - if (!user::active()->admin) { + if (!Session::active_user()->admin) { access::forbidden(); } diff --git a/modules/gallery/controllers/login.php b/modules/gallery/controllers/login.php index 2c4bd557..4c83d647 100644 --- a/modules/gallery/controllers/login.php +++ b/modules/gallery/controllers/login.php @@ -21,7 +21,7 @@ class Login_Controller extends Controller { public function ajax() { $view = new View("login_ajax.html"); - $view->form = user::get_login_form("login/auth_ajax"); + $view->form = login::get_login_form("login/auth_ajax"); print $view; } @@ -40,7 +40,7 @@ class Login_Controller extends Controller { } public function html() { - print user::get_login_form("login/auth_html"); + print login::get_login_form("login/auth_html"); } public function auth_html() { @@ -53,12 +53,13 @@ class Login_Controller extends Controller { print $form; } } + private function _auth($url) { - $form = user::get_login_form($url); + $form = login::get_login_form($url); $valid = $form->validate(); if ($valid) { - $user = user::lookup_by_name($form->login->inputs["name"]->value); - if (empty($user) || !user::is_correct_password($user, $form->login->password->value)) { + $user = Identity::lookup_user_by_name($form->login->inputs["name"]->value); + if (empty($user) || !Identity::is_correct_password($user, $form->login->password->value)) { log::warning( "user", t("Failed login for %name", @@ -69,7 +70,12 @@ class Login_Controller extends Controller { } if ($valid) { - user::login($user); + if (Identity::is_writable()) { + $user->login_count += 1; + $user->last_login = time(); + $user->save(); + } + Session::set_active_user($user); log::info("user", t("User %name logged in", array("name" => $user->name))); } diff --git a/modules/gallery/controllers/logout.php b/modules/gallery/controllers/logout.php index 45d397ad..058860fa 100644 --- a/modules/gallery/controllers/logout.php +++ b/modules/gallery/controllers/logout.php @@ -19,10 +19,15 @@ */ class Logout_Controller extends Controller { public function index() { - //access::verify_csrf(); - - $user = user::active(); - user::logout(); + $user = Session::active_user(); + if (!$user->guest) { + try { + Session::instance()->destroy(); + } catch (Exception $e) { + Kohana::log("error", $e); + } + module::event("user_logout", $user); + } log::info("user", t("User %name logged out", array("name" => $user->name)), html::anchor("user/$user->id", html::clean($user->name))); if ($continue_url = $this->input->get("continue")) { diff --git a/modules/gallery/controllers/permissions.php b/modules/gallery/controllers/permissions.php index 8d75862e..58c5b816 100644 --- a/modules/gallery/controllers/permissions.php +++ b/modules/gallery/controllers/permissions.php @@ -51,13 +51,13 @@ class Permissions_Controller extends Controller { function change($command, $group_id, $perm_id, $item_id) { access::verify_csrf(); - $group = ORM::factory("group", $group_id); + $group = Identity::lookup_group($group_id); $perm = ORM::factory("permission", $perm_id); $item = ORM::factory("item", $item_id); access::required("view", $item); access::required("edit", $item); - if ($group->loaded && $perm->loaded && $item->loaded) { + if (!empty($group) && $perm->loaded && $item->loaded) { switch($command) { case "allow": access::allow($group, $perm->name, $item); @@ -74,7 +74,7 @@ class Permissions_Controller extends Controller { // If the active user just took away their own edit permissions, give it back. if ($perm->name == "edit") { - if (!access::user_can(user::active(), "edit", $item)) { + if (!access::user_can(Session::active_user(), "edit", $item)) { access::allow($group, $perm->name, $item); } } @@ -84,7 +84,7 @@ class Permissions_Controller extends Controller { private function _get_form($item) { $view = new View("permissions_form.html"); $view->item = $item; - $view->groups = ORM::factory("group")->find_all(); + $view->groups = Identity::groups(); $view->permissions = ORM::factory("permission")->find_all(); return $view; } diff --git a/modules/gallery/controllers/upgrader.php b/modules/gallery/controllers/upgrader.php index 0f6cbc2c..e0c5d340 100644 --- a/modules/gallery/controllers/upgrader.php +++ b/modules/gallery/controllers/upgrader.php @@ -40,7 +40,7 @@ class Upgrader_Controller extends Controller { } $view = new View("upgrader.html"); - $view->can_upgrade = user::active()->admin || $session->get("can_upgrade"); + $view->can_upgrade = Session::active_user()->admin || $session->get("can_upgrade"); $view->upgrade_token = $upgrade_token; $view->available = module::available(); $view->done = ($available_upgrades == 0); @@ -52,7 +52,7 @@ class Upgrader_Controller extends Controller { // @todo this may screw up some module installers, but we don't have a better answer at // this time. $_SERVER["HTTP_HOST"] = "example.com"; - } else if (!user::active()->admin && !Session::instance()->get("can_upgrade", false)) { + } else if (!Session::active_user()->admin && !Session::instance()->get("can_upgrade", false)) { access::forbidden(); } diff --git a/modules/gallery/controllers/welcome_message.php b/modules/gallery/controllers/welcome_message.php index 8fd1e0a0..cfdc3976 100644 --- a/modules/gallery/controllers/welcome_message.php +++ b/modules/gallery/controllers/welcome_message.php @@ -19,12 +19,12 @@ */ class Welcome_Message_Controller extends Controller { public function index() { - if (!user::active()->admin) { + if (!Session::active_user()->admin) { url::redirect(item::root()->abs_url()); } $v = new View("welcome_message.html"); - $v->user = user::active(); + $v->user = Session::active_user(); print $v; } } diff --git a/modules/gallery/helpers/access.php b/modules/gallery/helpers/access.php index 949aea84..4e7491e3 100644 --- a/modules/gallery/helpers/access.php +++ b/modules/gallery/helpers/access.php @@ -79,7 +79,7 @@ class access_Core { * @return boolean */ static function can($perm_name, $item) { - return self::user_can(user::active(), $perm_name, $item); + return self::user_can(Session::active_user(), $perm_name, $item); } /** @@ -197,8 +197,8 @@ class access_Core { * @param Item_Model $item * @param boolean $value */ - private static function _set(Group_Model $group, $perm_name, $album, $value) { - if (get_class($group) != "Group_Model") { + private static function _set(Group_Definition $group, $perm_name, $album, $value) { + if (!($group instanceof Group_Definition)) { throw new Exception("@todo PERMISSIONS_ONLY_WORK_ON_GROUPS"); } if (!$album->loaded) { @@ -419,10 +419,11 @@ class access_Core { * @return ORM_Iterator */ private static function _get_all_groups() { - // When we build the gallery package, it's possible that the user module is not installed yet. + // When we build the gallery package, it's possible that there is no identity provider installed yet. // This is ok at packaging time, so work around it. - if (module::is_active("user")) { - return ORM::factory("group")->find_all(); + $config = module::get_var("gallery", "identity_provider"); + if (!empty($config)) { + return Identity::groups(); } else { return array(); } diff --git a/modules/gallery/helpers/gallery.php b/modules/gallery/helpers/gallery.php index 50e2c43b..18bb2609 100644 --- a/modules/gallery/helpers/gallery.php +++ b/modules/gallery/helpers/gallery.php @@ -27,7 +27,7 @@ class gallery_Core { static function maintenance_mode() { $maintenance_mode = Kohana::config("core.maintenance_mode", false, false); - if (Router::$controller != "login" && !empty($maintenance_mode) && !user::active()->admin) { + if (Router::$controller != "login" && !empty($maintenance_mode) && !Session::active_user()->admin) { Router::$controller = "maintenance"; Router::$controller_path = MODPATH . "gallery/controllers/maintenance.php"; Router::$method = "index"; diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php index e0de2152..95be4813 100644 --- a/modules/gallery/helpers/gallery_event.php +++ b/modules/gallery/helpers/gallery_event.php @@ -23,7 +23,11 @@ class gallery_event_Core { * Initialization. */ static function gallery_ready() { - user::load_user(); + // Call Identity::instance() now to force the load of the user interface classes. + // Session::load_user will attempt to load the active user from the session and needs + // the user definition class, which can't be reached by Kohana's heiracrchical lookup. + Identity::instance(); + Session::load_user(); locales::set_request_locale(); } @@ -135,7 +139,7 @@ class gallery_event_Core { } } - if (user::active()->admin) { + if (Session::active_user()->admin) { $menu->append($admin_menu = Menu::factory("submenu") ->id("admin_menu") ->label(t("Admin"))); @@ -186,11 +190,19 @@ class gallery_event_Core { ->append(Menu::factory("link") ->id("sidebar") ->label(t("Manage Sidebar")) - ->url(url::site("admin/sidebar")))) - ->append(Menu::factory("link") - ->id("users_groups") - ->label(t("Users/Groups")) - ->url(url::site("admin/users"))) + ->url(url::site("admin/sidebar")))); + if (count(Identity::providers()) > 1) { + $menu + ->append(Menu::factory("submenu") + ->id("identity_menu") + ->label(t("Identity Management")) + ->append(Menu::factory("link") + ->id("identity_drivers") + ->label(t("Identity Drivers")) + ->url(url::site("admin/identity")))); + } + + $menu ->append(Menu::factory("submenu") ->id("statistics_menu") ->label(t("Statistics"))) diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php index b1ea1f19..10e796fd 100644 --- a/modules/gallery/helpers/gallery_installer.php +++ b/modules/gallery/helpers/gallery_installer.php @@ -317,7 +317,7 @@ class gallery_installer { } if ($version == 7) { - $groups = ORM::factory("group")->find_all(); + $groups = Identity::groups(); $permissions = ORM::factory("permission")->find_all(); foreach($groups as $group) { foreach($permissions as $permission) { diff --git a/modules/gallery/helpers/gallery_theme.php b/modules/gallery/helpers/gallery_theme.php index a342b4bd..d21cb124 100644 --- a/modules/gallery/helpers/gallery_theme.php +++ b/modules/gallery/helpers/gallery_theme.php @@ -54,7 +54,7 @@ class gallery_theme_Core { static function header_top($theme) { if ($theme->page_type != "login") { $view = new View("login.html"); - $view->user = user::active(); + $view->user = Session::active_user(); return $view->render(); } } diff --git a/modules/gallery/helpers/item.php b/modules/gallery/helpers/item.php index 084bbc15..3d36a324 100644 --- a/modules/gallery/helpers/item.php +++ b/modules/gallery/helpers/item.php @@ -158,8 +158,8 @@ class item_Core { */ static function viewable($model) { $view_restrictions = array(); - if (!user::active()->admin) { - foreach (user::group_ids() as $id) { + if (!Session::active_user()->admin) { + foreach (Session::group_ids_for_active_user() as $id) { // Separate the first restriction from the rest to make it easier for us to formulate // our where clause below if (empty($view_restrictions)) { diff --git a/modules/gallery/helpers/locales.php b/modules/gallery/helpers/locales.php index f0807c99..f80fce03 100644 --- a/modules/gallery/helpers/locales.php +++ b/modules/gallery/helpers/locales.php @@ -136,6 +136,23 @@ class locales_Core { return in_array($language, array("he", "fa", "ar")); } + static function set_request_locale() { + // 1. Check the session specific preference (cookie) + $locale = self::cookie_locale(); + // 2. Check the user's preference + if (!$locale) { + $locale = Session::active_user()->locale; + } + // 3. Check the browser's / OS' preference + if (!$locale) { + $locale = self::locale_from_http_request(); + } + // If we have any preference, override the site's default locale + if ($locale) { + I18n::instance()->locale($locale); + } + } + /** * Returns the best match comparing the HTTP accept-language header * with the installed locales. @@ -220,23 +237,6 @@ class locales_Core { return array(null, 0); } - static function set_request_locale() { - // 1. Check the session specific preference (cookie) - $locale = self::cookie_locale(); - // 2. Check the user's preference - if (!$locale) { - $locale = user::active()->locale; - } - // 3. Check the browser's / OS' preference - if (!$locale) { - $locale = locales::locale_from_http_request(); - } - // If we have any preference, override the site's default locale - if ($locale) { - I18n::instance()->locale($locale); - } - } - static function cookie_locale() { $cookie_data = Input::instance()->cookie("g_locale"); $locale = null; diff --git a/modules/gallery/helpers/log.php b/modules/gallery/helpers/log.php index c8e94b45..d1b34e3a 100644 --- a/modules/gallery/helpers/log.php +++ b/modules/gallery/helpers/log.php @@ -80,7 +80,7 @@ class log_Core { $log->url = substr(url::abs_current(true), 0, 255); $log->referer = request::referrer(null); $log->timestamp = time(); - $log->user_id = user::active()->id; + $log->user_id = Session::active_user()->id; $log->save(); } diff --git a/modules/gallery/helpers/login.php b/modules/gallery/helpers/login.php new file mode 100644 index 00000000..d44153ad --- /dev/null +++ b/modules/gallery/helpers/login.php @@ -0,0 +1,31 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2009 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +class login_Core { + static function get_login_form($url) { + $form = new Forge($url, "", "post", array("id" => "g-login-form")); + $form->set_attr('class', "g-narrow"); + $group = $form->group("login")->label(t("Login")); + $group->input("name")->label(t("Username"))->id("g-username")->class(null); + $group->password("password")->label(t("Password"))->id("g-password")->class(null); + $group->inputs["name"]->error_messages("invalid_login", t("Invalid name or password")); + $group->submit("")->value(t("Login")); + return $form; + } +}
\ No newline at end of file diff --git a/modules/gallery/helpers/module.php b/modules/gallery/helpers/module.php index 77ec6f63..fb298959 100644 --- a/modules/gallery/helpers/module.php +++ b/modules/gallery/helpers/module.php @@ -103,7 +103,8 @@ class module_Core { // Lock certain modules $modules->gallery->locked = true; - $modules->user->locked = true; + $identity_module = self::get_var("gallery", "identity_provider", "user"); + $modules->$identity_module->locked = true; $modules->ksort(); self::$available = $modules; } diff --git a/modules/gallery/helpers/movie.php b/modules/gallery/helpers/movie.php index 9ca28fe6..9541f20e 100644 --- a/modules/gallery/helpers/movie.php +++ b/modules/gallery/helpers/movie.php @@ -77,7 +77,7 @@ class movie_Core { $movie->title = $title; $movie->description = $description; $movie->name = $name; - $movie->owner_id = $owner_id ? $owner_id : user::active(); + $movie->owner_id = $owner_id ? $owner_id : Session::active_user()->id; $movie->width = $movie_info[0]; $movie->height = $movie_info[1]; $movie->mime_type = strtolower($pi["extension"]) == "mp4" ? "video/mp4" : "video/x-flv"; diff --git a/modules/gallery/helpers/photo.php b/modules/gallery/helpers/photo.php index d1d8fb1f..193293e8 100644 --- a/modules/gallery/helpers/photo.php +++ b/modules/gallery/helpers/photo.php @@ -76,7 +76,7 @@ class photo_Core { $photo->title = $title; $photo->description = $description; $photo->name = $name; - $photo->owner_id = $owner_id ? $owner_id : user::active(); + $photo->owner_id = $owner_id ? $owner_id : Session::active_user()->id; $photo->width = $image_info[0]; $photo->height = $image_info[1]; $photo->mime_type = empty($image_info['mime']) ? "application/unknown" : $image_info['mime']; diff --git a/modules/gallery/helpers/site_status.php b/modules/gallery/helpers/site_status.php index b7c6de9a..06b29fda 100644 --- a/modules/gallery/helpers/site_status.php +++ b/modules/gallery/helpers/site_status.php @@ -95,7 +95,7 @@ class site_status_Core { * @return html text */ static function get() { - if (!user::active()->admin) { + if (!Session::active_user()->admin) { return; } $buf = array(); diff --git a/modules/gallery/helpers/task.php b/modules/gallery/helpers/task.php index 9fa04305..f84fd10e 100644 --- a/modules/gallery/helpers/task.php +++ b/modules/gallery/helpers/task.php @@ -42,7 +42,7 @@ class task_Core { $task->percent_complete = 0; $task->status = ""; $task->state = "started"; - $task->owner_id = user::active()->id; + $task->owner_id = Session::active_user()->id; $task->context = serialize($context); $task->save(); diff --git a/modules/gallery/helpers/user.php b/modules/gallery/helpers/user.php deleted file mode 100644 index e7e75d64..00000000 --- a/modules/gallery/helpers/user.php +++ /dev/null @@ -1,279 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access."); -/** - * Gallery - a web based photo album viewer and editor - * Copyright (C) 2000-2009 Bharat Mediratta - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/** - * This is the API for handling users. - * - * Note: by design, this class does not do any permission checking. - */ -class user_Core { - static function get_login_form($url) { - $form = new Forge($url, "", "post", array("id" => "g-login-form")); - $form->set_attr('class', "g-narrow"); - $group = $form->group("login")->label(t("Login")); - $group->input("name")->label(t("Username"))->id("g-username")->class(null); - $group->password("password")->label(t("Password"))->id("g-password")->class(null); - $group->inputs["name"]->error_messages("invalid_login", t("Invalid name or password")); - $group->submit("")->value(t("Login")); - return $form; - } - - /** - * Make sure that we have a session and group_ids cached in the session. - */ - static function load_user() { - $session = Session::instance(); - if (!($user = $session->get("user"))) { - $session->set("user", $user = user::guest()); - } - - // The installer cannot set a user into the session, so it just sets an id which we should - // upconvert into a user. - if ($user === 2) { - $user = model_cache::get("user", 2); - user::login($user); - $session->set("user", $user); - } - - if (!$session->get("group_ids")) { - $ids = array(); - foreach ($user->groups as $group) { - $ids[] = $group->id; - } - $session->set("group_ids", $ids); - } - } - - /** - * Return the array of group ids this user belongs to - * - * @return array - */ - static function group_ids() { - return Session::instance()->get("group_ids", array(1)); - } - - /** - * Return the active user. If there's no active user, return the guest user. - * - * @return User_Model - */ - static function active() { - // @todo (maybe) cache this object so we're not always doing session lookups. - $user = Session::instance()->get("user", null); - if (!isset($user)) { - // Don't do this as a fallback in the Session::get() call because it can trigger unnecessary - // work. - $user = user::guest(); - } - return $user; - } - - /** - * Return the guest user. - * - * @todo consider caching - * - * @return User_Model - */ - static function guest() { - return model_cache::get("user", 1); - } - - /** - * Change the active user. - * - * @return User_Model - */ - static function set_active($user) { - $session = Session::instance(); - $session->set("user", $user); - $session->delete("group_ids"); - self::load_user(); - } - - /** - * Create a new user. - * - * @param string $name - * @param string $full_name - * @param string $password - * @return User_Model - */ - static function create($name, $full_name, $password) { - $user = ORM::factory("user")->where("name", $name)->find(); - if ($user->loaded) { - throw new Exception("@todo USER_ALREADY_EXISTS $name"); - } - - $user->name = $name; - $user->full_name = $full_name; - $user->password = $password; - - // Required groups - $user->add(group::everybody()); - $user->add(group::registered_users()); - - $user->save(); - return $user; - } - - /** - * Is the password provided correct? - * - * @param user User Model - * @param string $password a plaintext password - * @return boolean true if the password is correct - */ - static function is_correct_password($user, $password) { - $valid = $user->password; - - // Try phpass first, since that's what we generate. - if (strlen($valid) == 34) { - require_once(MODPATH . "user/lib/PasswordHash.php"); - $hashGenerator = new PasswordHash(10, true); - return $hashGenerator->CheckPassword($password, $valid); - } - - $salt = substr($valid, 0, 4); - // Support both old (G1 thru 1.4.0; G2 thru alpha-4) and new password schemes: - $guess = (strlen($valid) == 32) ? md5($password) : ($salt . md5($salt . $password)); - if (!strcmp($guess, $valid)) { - return true; - } - - // Passwords with <&"> created by G2 prior to 2.1 were hashed with entities - $sanitizedPassword = html::specialchars($password, false); - $guess = (strlen($valid) == 32) ? md5($sanitizedPassword) - : ($salt . md5($salt . $sanitizedPassword)); - if (!strcmp($guess, $valid)) { - return true; - } - - return false; - } - - /** - * Create the hashed passwords. - * @param string $password a plaintext password - * @return string hashed password - */ - static function hash_password($password) { - require_once(MODPATH . "user/lib/PasswordHash.php"); - $hashGenerator = new PasswordHash(10, true); - return $hashGenerator->HashPassword($password); - } - - /** - * Log in as a given user. - * @param object $user the user object. - */ - static function login($user) { - $user->login_count += 1; - $user->last_login = time(); - $user->save(); - - user::set_active($user); - module::event("user_login", $user); - } - - /** - * Log out the active user and destroy the session. - * @param object $user the user object. - */ - static function logout() { - $user = user::active(); - if (!$user->guest) { - try { - Session::instance()->destroy(); - } catch (Exception $e) { - Kohana::log("error", $e); - } - module::event("user_logout", $user); - } - } - - /** - * Look up a user by id. - * @param integer $id the user id - * @return User_Model the user object, or null if the id was invalid. - */ - static function lookup($id) { - return self::_lookup_user_by_field("id", $id); - } - - /** - * Look up a user by name. - * @param integer $name the user name - * @return User_Model the user object, or null if the name was invalid. - */ - static function lookup_by_name($name) { - return self::_lookup_user_by_field("name", $name); - } - - /** - * Look up a user by hash. - * @param integer $hash the user hash value - * @return User_Model the user object, or null if the name was invalid. - */ - static function lookup_by_hash($hash) { - return self::_lookup_user_by_field("hash", $hash); - } - - /** - * List the users - * @param mixed filters (@see Database.php - * @return array the user list. - */ - static function get_user_list($filter=array()) { - $user = ORM::factory("user"); - - foreach($filter as $method => $args) { - switch ($method) { - case "in": - $user->in($args[0], $args[1]); - break; - default: - $user->$method($args); - } - } - return $user->find_all(); - } - - /** - * Look up a user by field value. - * @param string search field - * @param string search value - * @return User_Core the user object, or null if the name was invalid. - */ - private static function _lookup_user_by_field($field_name, $value) { - try { - $user = model_cache::get("user", $value, $field_name); - if ($user->loaded) { - return $user; - } - } catch (Exception $e) { - if (strpos($e->getMessage(), "MISSING_MODEL") === false) { - throw $e; - } - } - return null; - } -}
\ No newline at end of file diff --git a/modules/gallery/libraries/Admin_View.php b/modules/gallery/libraries/Admin_View.php index fa6d1dd3..74a08c77 100644 --- a/modules/gallery/libraries/Admin_View.php +++ b/modules/gallery/libraries/Admin_View.php @@ -36,12 +36,12 @@ class Admin_View_Core extends Gallery_View { parent::__construct($name); $this->theme_name = module::get_var("gallery", "active_admin_theme"); - if (user::active()->admin) { + if (Session::active_user()->admin) { $this->theme_name = Input::instance()->get("theme", $this->theme_name); } $this->sidebar = ""; $this->set_global("theme", $this); - $this->set_global("user", user::active()); + $this->set_global("user", Session::active_user()); } public function admin_menu() { diff --git a/modules/gallery/libraries/Identity.php b/modules/gallery/libraries/Identity.php new file mode 100644 index 00000000..1dd5d23b --- /dev/null +++ b/modules/gallery/libraries/Identity.php @@ -0,0 +1,222 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2009 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * Provides a driver-based interface for managing users and groups. + */ +class Identity_Core { + protected static $instance; + + protected static $active; + + // Configuration + protected $config; + + // Driver object + protected $driver; + + /** + * Returns a singleton instance of Identity. + * There can only be one Identity driver configured at a given point + * + * @param string configuration + * @return Identity_Core + */ + static function & instance() { + if (!isset(self::$instance)) { + // Create a new instance + self::$instance = new Identity(); + } + + return self::$instance; + } + + /** + * Returns a singleton instance of Identity. + * There can only be one Identity driver configured at a given point + * + * @param string configuration + * @return Identity_Core + */ + static function reset() { + self::$instance = new Identity(); + } + + /** + * Loads the configured driver and validates it. + * + * @return void + */ + public function __construct() { + $config = module::get_var("gallery", "identity_provider", "user"); + + // Test the config group name + if (($this->config = Kohana::config("identity.".$config)) === NULL) { + throw new Exception("@todo NO USER LIBRARY CONFIGURATION FOR: $config"); + } + + // Set driver name + $driver = "Identity_".ucfirst($this->config["driver"])."_Driver"; + + // Load the driver + if ( ! Kohana::auto_load($driver)) { + throw new Kohana_Exception("core.driver_not_found", $this->config["driver"], + get_class($this)); + } + + // Initialize the driver + $this->driver = new $driver($this->config["params"]); + + // Validate the driver + if ( !($this->driver instanceof Identity_Driver)) { + throw new Kohana_Exception("core.driver_implements", $this->config["driver"], + get_class($this), "Identity_Driver"); + } + + Kohana::log("debug", "Identity Library initialized"); + } + + /** + * Return a list of installed Identity Drivers. + * + * @return boolean true if the driver supports updates; false if read only + */ + static function providers() { + if (empty(self::$active)) { + $drivers = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS); + foreach (module::active() as $module) { + $module_name = $module->name; + if (file_exists(MODPATH . "{$module->name}/config/identity.php") && + ($info = module::info($module_name))) { + $drivers->$module_name = $info->description; + } + } + self::$active = $drivers; + } + return self::$active; + } + + /** + * @see Identity_Driver::activate. + */ + static function activate() { + self::instance()->driver->activate(); + } + + /** + * @see Identity_Driver::deactivate. + */ + static function deactivate() { + self::instance()->driver->deactivate(); + } + + /** + * Determine if if the current driver supports updates. + * + * @return boolean true if the driver supports updates; false if read only + */ + static function is_writable() { + return !empty(self::instance()->config["allow_updates"]); + } + + /** + * @see Identity_Driver::guest. + */ + static function guest() { + return self::instance()->driver->guest(); + } + + /** + * @see Identity_Driver::create_user. + */ + static function create_user($name, $full_name, $password) { + return self::instance()->driver->create_user($name, $full_name, $password); + } + + /** + * @see Identity_Driver::is_correct_password. + */ + static function is_correct_password($user, $password) { + return self::instance()->driver->is_correct_password($user, $password); + } + + /** + * @see Identity_Driver::lookup_user. + */ + static function lookup_user($id) { + return self::instance()->driver->lookup_user($id); + } + + /** + * @see Identity_Driver::lookup_user_by_name. + */ + static function lookup_user_by_name($name) { + return self::instance()->driver->lookup_user_by_name($name); + } + + /** + * @see Identity_Driver::create_group. + */ + static function create_group($name) { + return self::instance()->driver->create_group($name); + } + + /** + * @see Identity_Driver::everybody. + */ + static function everybody() { + return self::instance()->driver->everybody(); + } + + /** + * @see Identity_Driver::registered_users. + */ + static function registered_users() { + return self::instance()->driver->everybody(); + } + + /** + * @see Identity_Driver::lookup_group. + */ + static function lookup_group($id) { + return self::instance()->driver->lookup_group($id); + } + + /** + * @see Identity_Driver::lookup_group_by_name. + */ + static function lookup_group_by_name($name) { + return self::instance()->driver->lookup_group_by_name($name); + } + + /** + * @see Identity_Driver::get_user_list. + */ + static function get_user_list($ids) { + return self::instance()->driver->get_user_list($ids); + } + + /** + * @see Identity_Driver::groups. + */ + static function groups() { + return self::instance()->driver->groups(); + } +} // End Identity diff --git a/modules/gallery/libraries/MY_Session.php b/modules/gallery/libraries/MY_Session.php new file mode 100644 index 00000000..1a3ae801 --- /dev/null +++ b/modules/gallery/libraries/MY_Session.php @@ -0,0 +1,93 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2009 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +class Session extends Session_Core { + /** + * Make sure that we have a session and group_ids cached in the session. + */ + static function load_user() { + try { + $session = Session::instance(); + if (!($user = $session->get("user"))) { + $session->set("user", $user = Identity::guest()); + } + + // The installer cannot set a user into the session, so it just sets an id which we should + // upconvert into a user. + // @todo set the user name into the session instead of 2 and then use it to get the user object + if ($user === 2) { + $user = Instance::lookup_user_by_name("admin"); + self::set_active_user($user); + $session->set("user", $user); + } + + if (!$session->get("group_ids")) { + $ids = array(); + foreach ($user->groups as $group) { + $ids[] = $group->id; + } + $session->set("group_ids", $ids); + } + } catch (Exception $e) { + try { + Session::instance()->destroy(); + } catch (Exception $e) { + // We don't care if there was a problem destroying the session. + } + url::redirect(item::root()->abs_url()); + } + } + + /** + * Return the array of group ids this user belongs to + * + * @return array + */ + static function group_ids_for_active_user() { + return self::instance()->get("group_ids", array(1)); + } + + /** + * Return the active user. If there's no active user, return the guest user. + * + * @return User_Definition + */ + static function active_user() { + // @todo (maybe) cache this object so we're not always doing session lookups. + $user = self::instance()->get("user", null); + if (!isset($user)) { + // Don't do this as a fallback in the Session::get() call because it can trigger unnecessary + // work. + $user = Identity::guest(); + } + return $user; + } + + /** + * Change the active user. + * @param User_Definition $user + */ + static function set_active_user($user) { + $session = Session::instance(); + $session->set("user", $user); + $session->delete("group_ids"); + self::load_user(); + } +}
\ No newline at end of file diff --git a/modules/gallery/libraries/Theme_View.php b/modules/gallery/libraries/Theme_View.php index cba436e8..2fdc7531 100644 --- a/modules/gallery/libraries/Theme_View.php +++ b/modules/gallery/libraries/Theme_View.php @@ -37,13 +37,13 @@ class Theme_View_Core extends Gallery_View { parent::__construct($name); $this->theme_name = module::get_var("gallery", "active_site_theme"); - if (user::active()->admin) { + if (Session::active_user()->admin) { $this->theme_name = Input::instance()->get("theme", $this->theme_name); } $this->item = null; $this->tag = null; $this->set_global("theme", $this); - $this->set_global("user", user::active()); + $this->set_global("user", Session::active_user()); $this->set_global("page_type", $page_type); $this->set_global("page_title", null); if ($page_type == "album") { @@ -158,7 +158,7 @@ class Theme_View_Core extends Gallery_View { */ public function sidebar_blocks() { $sidebar = block_manager::get_html("site.sidebar", $this); - if (empty($sidebar) && user::active()->admin) { + if (empty($sidebar) && Session::active_user()->admin) { $sidebar = new View("no_sidebar.html"); } return $sidebar; diff --git a/modules/gallery/libraries/drivers/Identity.php b/modules/gallery/libraries/drivers/Identity.php new file mode 100644 index 00000000..39b2a9c7 --- /dev/null +++ b/modules/gallery/libraries/drivers/Identity.php @@ -0,0 +1,123 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2009 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +interface Identity_Driver { + /** + * Initialize the provider so it is ready to use + */ + public function activate(); + + /** + * Cleanup up this provider so it is unavailable for use and won't conflict with the current driver + */ + public function deactivate(); + + /** + * Return the guest user. + * + * @return User_Definition the user object + */ + public function guest(); + + /** + * Create a new user. + * + * @param string $name + * @param string $full_name + * @param string $password + * @return User_Definition the user object + */ + public function create_user($name, $full_name, $password); + + /** + * Is the password provided correct? + * + * @param user User_Definition the user object + * @param string $password a plaintext password + * @return boolean true if the password is correct + */ + public function is_correct_password($user, $password); + + /** + * Look up a user by id. + * @param integer id + * @return User_Definition the user object, or null if the name was invalid. + */ + public function lookup_user($id); + + /** + * Look up a user by name. + * @param string name + * @return User_Definition the user object, or null if the name was invalid. + */ + public function lookup_user_by_name($name); + + /** + * Create a new group. + * + * @param string $name + * @return Group_Definition the group object + */ + public function create_group($name); + + /** + * The group of all possible visitors. This includes the guest user. + * + * @return Group_Definition the group object + */ + public function everybody(); + + /** + * The group of all logged-in visitors. This does not include guest users. + * + * @return Group_Definition the group object + */ + public function registered_users(); + + /** + * List the users + * @param array array of ids to return the user objects for + * @return array the user list. + */ + public function get_user_list($ids); + + /** + * Look up a group by id. + * @param integer id + * @return Group_Definition the user object, or null if the name was invalid. + */ + public function lookup_group($id); + + /** + * Look up the group by name. + * @param string $name the name of the group to locate + * @return Group_Definition + */ + public function lookup_group_by_name($name); + + /** + * List the groups defined in the Identity Provider + */ + public function groups(); + +} // End Identity Driver Definition + +interface Group_Definition {} + +interface User_Definition {} diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php index 6f0e3525..ba44709f 100644 --- a/modules/gallery/models/item.php +++ b/modules/gallery/models/item.php @@ -333,7 +333,7 @@ class Item_Model extends ORM_MPTT { // This relationship depends on an outside module, which may not be present so handle // failures gracefully. try { - return user::lookup($this->owner_id); + return Identity::lookup_user($this->owner_id); } catch (Exception $e) { return null; } diff --git a/modules/gallery/models/log.php b/modules/gallery/models/log.php index d143d7bd..1d639857 100644 --- a/modules/gallery/models/log.php +++ b/modules/gallery/models/log.php @@ -26,7 +26,7 @@ class Log_Model extends ORM { // This relationship depends on an outside module, which may not be present so handle // failures gracefully. try { - return user::lookup($this->user_id); + return Identity::lookup_user($this->user_id); } catch (Exception $e) { return null; } diff --git a/modules/gallery/models/task.php b/modules/gallery/models/task.php index b7e255a2..548e5f9c 100644 --- a/modules/gallery/models/task.php +++ b/modules/gallery/models/task.php @@ -46,7 +46,7 @@ class Task_Model extends ORM { } public function owner() { - return user::lookup($this->owner_id); + return Identity::lookup_user($this->owner_id); } /** diff --git a/modules/gallery/tests/Access_Helper_Test.php b/modules/gallery/tests/Access_Helper_Test.php index 72d7e04c..dac431a7 100644 --- a/modules/gallery/tests/Access_Helper_Test.php +++ b/modules/gallery/tests/Access_Helper_Test.php @@ -22,8 +22,8 @@ class Access_Helper_Test extends Unit_Test_Case { public function teardown() { try { - $group = ORM::factory("group")->where("name", "access_test")->find(); - if ($group->loaded) { + $group = Identity::lookup_group_by_name("access_test"); + if (!empty($group)) { $group->delete(); } } catch (Exception $e) { } @@ -33,24 +33,24 @@ class Access_Helper_Test extends Unit_Test_Case { } catch (Exception $e) { } try { - $user = user::lookup_by_name("access_test"); - if ($user->loaded) { + $user = Identity::lookup_user_by_name("access_test"); + if (!empty($user)) { $user->delete(); } } catch (Exception $e) { } // Reset some permissions that we mangle below $root = ORM::factory("item", 1); - access::allow(group::everybody(), "view", $root); + access::allow(Identity::everybody(), "view", $root); } public function setup() { - user::set_active(user::guest()); + Session::set_active_user(Identity::guest()); } public function groups_and_permissions_are_bound_to_columns_test() { access::register_permission("access_test", "Access Test"); - $group = group::create("access_test"); + $group = Identity::create_group("access_test"); // We have a new column for this perm / group combo $fields = Database::instance()->list_fields("access_caches"); @@ -65,17 +65,17 @@ class Access_Helper_Test extends Unit_Test_Case { } public function user_can_access_test() { - $access_test = group::create("access_test"); + $access_test = Identity::create_group("access_test"); $root = ORM::factory("item", 1); access::allow($access_test, "view", $root); $item = album::create($root, rand(), "test album"); - access::deny(group::everybody(), "view", $item); - access::deny(group::registered_users(), "view", $item); + access::deny(Identity::everybody(), "view", $item); + access::deny(Identity::registered_users(), "view", $item); - $user = user::create("access_test", "Access Test", ""); + $user = Identity::create_user("access_test", "Access Test", ""); foreach ($user->groups as $group) { $user->remove($group); } @@ -89,10 +89,10 @@ class Access_Helper_Test extends Unit_Test_Case { $root = ORM::factory("item", 1); $item = album::create($root, rand(), "test album"); - access::deny(group::everybody(), "view", $item); - access::deny(group::registered_users(), "view", $item); + access::deny(Identity::everybody(), "view", $item); + access::deny(Identity::registered_users(), "view", $item); - $user = user::create("access_test", "Access Test", ""); + $user = Identity::create_user("access_test", "Access Test", ""); foreach ($user->groups as $group) { $user->remove($group); } @@ -121,14 +121,11 @@ class Access_Helper_Test extends Unit_Test_Case { $root = ORM::factory("item", 1); $album = album::create($root, rand(), "test album"); - access::allow(group::everybody(), "view", $album); + access::allow(Identity::everybody(), "view", $album); - $photo = ORM::factory("item"); - $photo->type = "photo"; - $photo->add_to_parent($album); - access::add_item($photo); + $photo = photo::create($album, MODPATH . "gallery/images/gallery.png", "", ""); - $this->assert_true($photo->__get("view_" . group::everybody()->id)); + $this->assert_true($photo->__get("view_" . Identity::everybody()->id)); } public function can_allow_deny_and_reset_intent_test() { @@ -137,23 +134,23 @@ class Access_Helper_Test extends Unit_Test_Case { $intent = ORM::factory("access_intent")->where("item_id", $album)->find(); // Allow - access::allow(group::everybody(), "view", $album); + access::allow(Identity::everybody(), "view", $album); $this->assert_same(access::ALLOW, $intent->reload()->view_1); // Deny - access::deny(group::everybody(), "view", $album); + access::deny(Identity::everybody(), "view", $album); $this->assert_same( access::DENY, ORM::factory("access_intent")->where("item_id", $album)->find()->view_1); // Allow again. If the initial value was allow, then the first Allow clause above may not // have actually changed any values. - access::allow(group::everybody(), "view", $album); + access::allow(Identity::everybody(), "view", $album); $this->assert_same( access::ALLOW, ORM::factory("access_intent")->where("item_id", $album)->find()->view_1); - access::reset(group::everybody(), "view", $album); + access::reset(Identity::everybody(), "view", $album); $this->assert_same( null, ORM::factory("access_intent")->where("item_id", $album)->find()->view_1); @@ -161,7 +158,7 @@ class Access_Helper_Test extends Unit_Test_Case { public function cant_reset_root_item_test() { try { - access::reset(group::everybody(), "view", ORM::factory("item", 1)); + access::reset(Identity::everybody(), "view", ORM::factory("item", 1)); } catch (Exception $e) { return; } @@ -170,17 +167,17 @@ class Access_Helper_Test extends Unit_Test_Case { public function can_view_item_test() { $root = ORM::factory("item", 1); - access::allow(group::everybody(), "view", $root); - $this->assert_true(access::group_can(group::everybody(), "view", $root)); + access::allow(Identity::everybody(), "view", $root); + $this->assert_true(access::group_can(Identity::everybody(), "view", $root)); } public function can_always_fails_on_unloaded_items_test() { $root = ORM::factory("item", 1); - access::allow(group::everybody(), "view", $root); - $this->assert_true(access::group_can(group::everybody(), "view", $root)); + access::allow(Identity::everybody(), "view", $root); + $this->assert_true(access::group_can(Identity::everybody(), "view", $root)); $bogus = ORM::factory("item", -1); - $this->assert_false(access::group_can(group::everybody(), "view", $bogus)); + $this->assert_false(access::group_can(Identity::everybody(), "view", $bogus)); } public function cant_view_child_of_hidden_parent_test() { @@ -188,21 +185,21 @@ class Access_Helper_Test extends Unit_Test_Case { $album = album::create($root, rand(), "test album"); $root->reload(); - access::deny(group::everybody(), "view", $root); - access::reset(group::everybody(), "view", $album); + access::deny(Identity::everybody(), "view", $root); + access::reset(Identity::everybody(), "view", $album); $album->reload(); - $this->assert_false(access::group_can(group::everybody(), "view", $album)); + $this->assert_false(access::group_can(Identity::everybody(), "view", $album)); } public function view_permissions_propagate_down_test() { $root = ORM::factory("item", 1); $album = album::create($root, rand(), "test album"); - access::allow(group::everybody(), "view", $root); - access::reset(group::everybody(), "view", $album); + access::allow(Identity::everybody(), "view", $root); + access::reset(Identity::everybody(), "view", $album); $album->reload(); - $this->assert_true(access::group_can(group::everybody(), "view", $album)); + $this->assert_true(access::group_can(Identity::everybody(), "view", $album)); } public function can_toggle_view_permissions_propagate_down_test() { @@ -217,18 +214,18 @@ class Access_Helper_Test extends Unit_Test_Case { $album3->reload(); $album4->reload(); - access::allow(group::everybody(), "view", $root); - access::deny(group::everybody(), "view", $album1); - access::reset(group::everybody(), "view", $album2); - access::reset(group::everybody(), "view", $album3); - access::reset(group::everybody(), "view", $album4); + access::allow(Identity::everybody(), "view", $root); + access::deny(Identity::everybody(), "view", $album1); + access::reset(Identity::everybody(), "view", $album2); + access::reset(Identity::everybody(), "view", $album3); + access::reset(Identity::everybody(), "view", $album4); $album4->reload(); - $this->assert_false(access::group_can(group::everybody(), "view", $album4)); + $this->assert_false(access::group_can(Identity::everybody(), "view", $album4)); - access::allow(group::everybody(), "view", $album1); + access::allow(Identity::everybody(), "view", $album1); $album4->reload(); - $this->assert_true(access::group_can(group::everybody(), "view", $album4)); + $this->assert_true(access::group_can(Identity::everybody(), "view", $album4)); } public function revoked_view_permissions_cant_be_allowed_lower_down_test() { @@ -237,29 +234,29 @@ class Access_Helper_Test extends Unit_Test_Case { $album2 = album::create($album1, rand(), "test album"); $root->reload(); - access::deny(group::everybody(), "view", $root); - access::allow(group::everybody(), "view", $album2); + access::deny(Identity::everybody(), "view", $root); + access::allow(Identity::everybody(), "view", $album2); $album1->reload(); - $this->assert_false(access::group_can(group::everybody(), "view", $album1)); + $this->assert_false(access::group_can(Identity::everybody(), "view", $album1)); $album2->reload(); - $this->assert_false(access::group_can(group::everybody(), "view", $album2)); + $this->assert_false(access::group_can(Identity::everybody(), "view", $album2)); } public function can_edit_item_test() { $root = ORM::factory("item", 1); - access::allow(group::everybody(), "edit", $root); - $this->assert_true(access::group_can(group::everybody(), "edit", $root)); + access::allow(Identity::everybody(), "edit", $root); + $this->assert_true(access::group_can(Identity::everybody(), "edit", $root)); } public function non_view_permissions_propagate_down_test() { $root = ORM::factory("item", 1); $album = album::create($root, rand(), "test album"); - access::allow(group::everybody(), "edit", $root); - access::reset(group::everybody(), "edit", $album); - $this->assert_true(access::group_can(group::everybody(), "edit", $album)); + access::allow(Identity::everybody(), "edit", $root); + access::reset(Identity::everybody(), "edit", $album); + $this->assert_true(access::group_can(Identity::everybody(), "edit", $album)); } public function non_view_permissions_can_be_revoked_lower_down_test() { @@ -279,36 +276,36 @@ class Access_Helper_Test extends Unit_Test_Case { $outer->reload(); $inner->reload(); - access::allow(group::everybody(), "edit", $root); - access::deny(group::everybody(), "edit", $outer); - access::allow(group::everybody(), "edit", $inner); + access::allow(Identity::everybody(), "edit", $root); + access::deny(Identity::everybody(), "edit", $outer); + access::allow(Identity::everybody(), "edit", $inner); // Outer album is not editable, inner one is. - $this->assert_false(access::group_can(group::everybody(), "edit", $outer_photo)); - $this->assert_true(access::group_can(group::everybody(), "edit", $inner_photo)); + $this->assert_false(access::group_can(Identity::everybody(), "edit", $outer_photo)); + $this->assert_true(access::group_can(Identity::everybody(), "edit", $inner_photo)); } public function i_can_edit_test() { // Create a new user that belongs to no groups - $user = user::create("access_test", "Access Test", ""); + $user = Identity::create_user("access_test", "Access Test", ""); foreach ($user->groups as $group) { $user->remove($group); } $user->save(); - user::set_active($user); + Session::set_active_user($user); // This user can't edit anything $root = ORM::factory("item", 1); $this->assert_false(access::can("edit", $root)); // Now add them to a group that has edit permission - $group = group::create("access_test"); + $group = Identity::create_group("access_test"); $group->add($user); $group->save(); access::allow($group, "edit", $root); - $user = user::lookup($user->id); // reload() does not flush related columns - user::set_active($user); + $user = Identity::lookup_user($user->id); // reload() does not flush related columns + Session::set_active_user($user); // And verify that the user can edit. $this->assert_true(access::can("edit", $root)); @@ -320,16 +317,16 @@ class Access_Helper_Test extends Unit_Test_Case { $this->assert_false(file_exists($album->file_path() . "/.htaccess")); - access::deny(group::everybody(), "view", $album); + access::deny(Identity::everybody(), "view", $album); $this->assert_true(file_exists($album->file_path() . "/.htaccess")); - access::allow(group::everybody(), "view", $album); + access::allow(Identity::everybody(), "view", $album); $this->assert_false(file_exists($album->file_path() . "/.htaccess")); - access::deny(group::everybody(), "view", $album); + access::deny(Identity::everybody(), "view", $album); $this->assert_true(file_exists($album->file_path() . "/.htaccess")); - access::reset(group::everybody(), "view", $album); + access::reset(Identity::everybody(), "view", $album); $this->assert_false(file_exists($album->file_path() . "/.htaccess")); } @@ -341,44 +338,44 @@ class Access_Helper_Test extends Unit_Test_Case { $this->assert_false(file_exists($album->resize_path() . "/.htaccess")); $this->assert_false(file_exists($album->thumb_path() . "/.htaccess")); - access::deny(group::everybody(), "view_full", $album); + access::deny(Identity::everybody(), "view_full", $album); $this->assert_true(file_exists($album->file_path() . "/.htaccess")); $this->assert_false(file_exists($album->resize_path() . "/.htaccess")); $this->assert_false(file_exists($album->thumb_path() . "/.htaccess")); - access::allow(group::everybody(), "view_full", $album); + access::allow(Identity::everybody(), "view_full", $album); $this->assert_false(file_exists($album->file_path() . "/.htaccess")); $this->assert_false(file_exists($album->resize_path() . "/.htaccess")); $this->assert_false(file_exists($album->thumb_path() . "/.htaccess")); - access::deny(group::everybody(), "view_full", $album); + access::deny(Identity::everybody(), "view_full", $album); $this->assert_true(file_exists($album->file_path() . "/.htaccess")); $this->assert_false(file_exists($album->resize_path() . "/.htaccess")); $this->assert_false(file_exists($album->thumb_path() . "/.htaccess")); - access::reset(group::everybody(), "view_full", $album); + access::reset(Identity::everybody(), "view_full", $album); $this->assert_false(file_exists($album->file_path() . "/.htaccess")); $this->assert_false(file_exists($album->resize_path() . "/.htaccess")); $this->assert_false(file_exists($album->thumb_path() . "/.htaccess")); } public function moved_items_inherit_new_permissions_test() { - user::set_active(user::lookup_by_name("admin")); + Session::set_active_user(Identity::lookup_user_by_name("admin")); $root = ORM::factory("item", 1); $public_album = album::create($root, rand(), "public album"); $public_photo = photo::create($public_album, MODPATH . "gallery/images/gallery.png", "", ""); - access::allow(group::everybody(), "view", $public_album); + access::allow(Identity::everybody(), "view", $public_album); $root->reload(); // Account for MPTT changes $private_album = album::create($root, rand(), "private album"); - access::deny(group::everybody(), "view", $private_album); + access::deny(Identity::everybody(), "view", $private_album); $private_photo = photo::create($private_album, MODPATH . "gallery/images/gallery.png", "", ""); // Make sure that we now have a public photo and private photo. - $this->assert_true(access::group_can(group::everybody(), "view", $public_photo)); - $this->assert_false(access::group_can(group::everybody(), "view", $private_photo)); + $this->assert_true(access::group_can(Identity::everybody(), "view", $public_photo)); + $this->assert_false(access::group_can(Identity::everybody(), "view", $private_photo)); // Swap the photos item::move($public_photo, $private_album); @@ -394,7 +391,7 @@ class Access_Helper_Test extends Unit_Test_Case { $public_photo->reload(); // Make sure that the public_photo is now private, and the private_photo is now public. - $this->assert_false(access::group_can(group::everybody(), "view", $public_photo)); - $this->assert_true(access::group_can(group::everybody(), "view", $private_photo)); + $this->assert_false(access::group_can(Identity::everybody(), "view", $public_photo)); + $this->assert_true(access::group_can(Identity::everybody(), "view", $private_photo)); } } diff --git a/modules/gallery/tests/Albums_Controller_Test.php b/modules/gallery/tests/Albums_Controller_Test.php index d65946c7..fa46d924 100644 --- a/modules/gallery/tests/Albums_Controller_Test.php +++ b/modules/gallery/tests/Albums_Controller_Test.php @@ -43,8 +43,9 @@ class Albums_Controller_Test extends Unit_Test_Case { $_POST["column"] = "weight"; $_POST["direction"] = "ASC"; $_POST["csrf"] = access::csrf_token(); + $_POST["slug"] = "new_name"; $_POST["_method"] = "put"; - access::allow(group::everybody(), "edit", $root); + access::allow(Identity::everybody(), "edit", $root); ob_start(); $controller->_update($this->_album); @@ -68,7 +69,7 @@ class Albums_Controller_Test extends Unit_Test_Case { $_POST["name"] = "new name"; $_POST["title"] = "new title"; $_POST["description"] = "new description"; - access::allow(group::everybody(), "edit", $root); + access::allow(Identity::everybody(), "edit", $root); try { $controller->_update($this->_album); diff --git a/modules/gallery/tests/File_Structure_Test.php b/modules/gallery/tests/File_Structure_Test.php index 9018f4c6..327b6be8 100644 --- a/modules/gallery/tests/File_Structure_Test.php +++ b/modules/gallery/tests/File_Structure_Test.php @@ -17,6 +17,8 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ +require_once(dirname(__FILE__) . "/Gallery_Filters.php"); + class File_Structure_Test extends Unit_Test_Case { public function no_trailing_closing_php_tag_test() { $dir = new GalleryCodeFilterIterator( @@ -233,7 +235,9 @@ class File_Structure_Test extends Unit_Test_Case { foreach ($info_files as $file) { foreach (file($file) as $line) { $parts = explode("=", $line, 2); - $values[trim($parts[0])] = trim($parts[1]); + if (isset($parts[1])) { + $values[trim($parts[0])] = trim($parts[1]); + } } $module = dirname($file); @@ -261,33 +265,3 @@ class File_Structure_Test extends Unit_Test_Case { } } } - -class PhpCodeFilterIterator extends FilterIterator { - public function accept() { - $path_name = $this->getInnerIterator()->getPathName(); - return substr($path_name, -4) == ".php"; - } -} - -class GalleryCodeFilterIterator extends FilterIterator { - public function accept() { - // Skip anything that we didn"t write - $path_name = $this->getInnerIterator()->getPathName(); - return !( - strpos($path_name, ".svn") || - strpos($path_name, DOCROOT . "test") !== false || - strpos($path_name, DOCROOT . "var") !== false || - strpos($path_name, MODPATH . "forge") !== false || - strpos($path_name, MODPATH . "gallery/views/kohana_error_page.php") !== false || - strpos($path_name, MODPATH . "gallery/views/kohana_profiler.php") !== false || - strpos($path_name, MODPATH . "gallery_unit_test/views/kohana_error_page.php") !== false || - strpos($path_name, MODPATH . "gallery_unit_test/views/kohana_unit_test_cli.php") !== false || - strpos($path_name, MODPATH . "unit_test") !== false || - strpos($path_name, MODPATH . "exif/lib") !== false || - strpos($path_name, MODPATH . "user/lib/PasswordHash") !== false || - strpos($path_name, DOCROOT . "lib/swfupload") !== false || - strpos($path_name, SYSPATH) !== false || - strpos($path_name, MODPATH . "gallery/libraries/HTMLPurifier") !== false || - substr($path_name, -1, 1) == "~"); - } -} diff --git a/modules/gallery/tests/Gallery_Filters.php b/modules/gallery/tests/Gallery_Filters.php new file mode 100644 index 00000000..d1bc2cfa --- /dev/null +++ b/modules/gallery/tests/Gallery_Filters.php @@ -0,0 +1,48 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2009 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +class PhpCodeFilterIterator extends FilterIterator { + public function accept() { + $path_name = $this->getInnerIterator()->getPathName(); + return substr($path_name, -4) == ".php"; + } +} + +class GalleryCodeFilterIterator extends FilterIterator { + public function accept() { + // Skip anything that we didn"t write + $path_name = $this->getInnerIterator()->getPathName(); + return !( + strpos($path_name, ".svn") || + strpos($path_name, DOCROOT . "test") !== false || + strpos($path_name, DOCROOT . "var") !== false || + strpos($path_name, MODPATH . "forge") !== false || + strpos($path_name, MODPATH . "gallery/views/kohana_error_page.php") !== false || + strpos($path_name, MODPATH . "gallery/views/kohana_profiler.php") !== false || + strpos($path_name, MODPATH . "gallery_unit_test/views/kohana_error_page.php") !== false || + strpos($path_name, MODPATH . "gallery_unit_test/views/kohana_unit_test_cli.php") !== false || + strpos($path_name, MODPATH . "unit_test") !== false || + strpos($path_name, MODPATH . "exif/lib") !== false || + strpos($path_name, MODPATH . "user/lib/PasswordHash") !== false || + strpos($path_name, DOCROOT . "lib/swfupload") !== false || + strpos($path_name, SYSPATH) !== false || + strpos($path_name, MODPATH . "gallery/libraries/HTMLPurifier") !== false || + substr($path_name, -1, 1) == "~"); + } +} diff --git a/modules/gallery/tests/Item_Helper_Test.php b/modules/gallery/tests/Item_Helper_Test.php index 33fcdb73..fc01db91 100644 --- a/modules/gallery/tests/Item_Helper_Test.php +++ b/modules/gallery/tests/Item_Helper_Test.php @@ -23,16 +23,16 @@ class Item_Helper_Test extends Unit_Test_Case { $root = ORM::factory("item", 1); $album = album::create($root, rand(), rand(), rand()); $item = self::_create_random_item($album); - user::set_active(user::guest()); + Session::set_active_user(Identity::guest()); // We can see the item when permissions are granted - access::allow(group::everybody(), "view", $album); + access::allow(Identity::everybody(), "view", $album); $this->assert_equal( 1, ORM::factory("item")->viewable()->where("id", $item->id)->count_all()); // We can't see the item when permissions are denied - access::deny(group::everybody(), "view", $album); + access::deny(Identity::everybody(), "view", $album); $this->assert_equal( 0, ORM::factory("item")->viewable()->where("id", $item->id)->count_all()); diff --git a/modules/gallery/tests/No_Direct_Access_Test.php b/modules/gallery/tests/No_Direct_Access_Test.php new file mode 100644 index 00000000..c6d8df95 --- /dev/null +++ b/modules/gallery/tests/No_Direct_Access_Test.php @@ -0,0 +1,77 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2009 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +require_once("Gallery_Filters.php"); + +class No_Direct_Access_Test extends Unit_Test_Case { + public function no_access_to_users_table_test() { + $dir = new UserModuleFilterIterator( + new PhpCodeFilterIterator( + new GalleryCodeFilterIterator( + new RecursiveIteratorIterator( + new RecursiveDirectoryIterator(DOCROOT))))); + $errors = array(); + foreach ($dir as $file) { + //if (basename(dirname($file)) == "helpers") { + $file_as_string = file_get_contents($file); + if (preg_match("/ORM::factory\\(\"user\"/", $file_as_string)) { + foreach (split("\n", $file_as_string) as $l => $line) { + if (preg_match('/ORM::factory\\(\"user\"/', $line)) { + $errors[] = "$file($l) => $line"; + } + } + } + $file_as_string = null; + } + if ($errors) { + $this->assert_false(true, "Direct access to the users table found:\n" . join("\n", $errors)); + } + } + + public function no_access_to_groups_table_test() { + $dir = new UserModuleFilterIterator( + new PhpCodeFilterIterator( + new GalleryCodeFilterIterator( + new RecursiveIteratorIterator( + new RecursiveDirectoryIterator(DOCROOT))))); + $errors = array(); + foreach ($dir as $file) { + $file_as_string = file_get_contents($file); + if (preg_match("/ORM::factory\\(\"group\"/", $file_as_string)) { + foreach (split("\n", $file_as_string) as $l => $line) { + if (preg_match('/ORM::factory\\(\"group\"/', $line)) { + $errors[] = "$file($l) => $line"; + } + } + } + $file_as_string = null; + } + if ($errors) { + $this->assert_false(true, "Direct access to the groups table found:\n" . join("\n", $errors)); + } + } + +} + +class UserModuleFilterIterator extends FilterIterator { + public function accept() { + $path_name = $this->getInnerIterator()->getPathName(); + return strpos($path_name, "/modules/user") === false; + } +} diff --git a/modules/gallery/tests/Photos_Controller_Test.php b/modules/gallery/tests/Photos_Controller_Test.php index 0159b420..59c3f78a 100644 --- a/modules/gallery/tests/Photos_Controller_Test.php +++ b/modules/gallery/tests/Photos_Controller_Test.php @@ -31,7 +31,7 @@ class Photos_Controller_Test extends Unit_Test_Case { $root = ORM::factory("item", 1); $photo = photo::create( $root, MODPATH . "gallery/tests/test.jpg", "test.jpeg", - "test", "test", user::active(), "slug"); + "test", "test", Session::active_user()->id, "slug"); $orig_name = $photo->name; $_POST["filename"] = "test.jpeg"; @@ -40,7 +40,7 @@ class Photos_Controller_Test extends Unit_Test_Case { $_POST["description"] = "new description"; $_POST["slug"] = "new-slug"; $_POST["csrf"] = access::csrf_token(); - access::allow(group::everybody(), "edit", $root); + access::allow(Identity::everybody(), "edit", $root); ob_start(); $controller->_update($photo); @@ -64,7 +64,7 @@ class Photos_Controller_Test extends Unit_Test_Case { $_POST["name"] = "new name"; $_POST["title"] = "new title"; $_POST["description"] = "new description"; - access::allow(group::everybody(), "edit", $root); + access::allow(Identity::everybody(), "edit", $root); try { $controller->_update($photo); diff --git a/modules/gallery/views/admin_identity.html.php b/modules/gallery/views/admin_identity.html.php new file mode 100644 index 00000000..1405cacb --- /dev/null +++ b/modules/gallery/views/admin_identity.html.php @@ -0,0 +1,61 @@ +<?php defined("SYSPATH") or die("No direct script access.") ?> +<script type="text/javascript"> + $(document).ready(function() { + $("#g-modules form").submit(function() { + var eDialog = '<div id="g-dialog"></div>'; + var params = $(this).serialize(); + var url = $(this).attr("action"); + $("body").append(eDialog); + $.post($(this).attr("action"), $(this).serialize(), function(data, textStatus) { + $("#g-dialog").html(data); + $("#g-dialog").dialog({ + bgiframe: true, + title: "<?= t("Confirm Change Identity Provider") ?>", + resizable: false, + height:165, + modal: true, + overlay: { + backgroundColor: '#000', + opacity: 0.5 + }, + buttons: { + "Continue": function() { + $("##g-dialog form").submit(); + }, + Cancel: function() { + $(this).dialog('close'); + } + } + }); + }); + return false; + }); + }); + +</script> +<div id="g-modules"> + <h1> <?= t("Gallery Identity Management") ?> </h1> + <p> + <?= t("Choose a different user/group management provider.") ?> + </p> + + <form method="post" action="<?= url::site("admin/identity/confirm") ?>"> + <?= access::csrf_form_field() ?> + <table> + <tr> + <th> <?= t("Active") ?> </th> + <th> <?= t("Description") ?> </th> + </tr> + <? $i = 0 ?> + <? foreach ($available as $module_name => $description): ?> + <tr class="<?= ($i % 2 == 0) ? "g-odd" : "g-even" ?>"> + <? $data = array("name" => "provider"); ?> + <td> <?= form::radio($data, $module_name, $module_name == $active) ?> </td> + <td> <?= t($description) ?> </td> + </tr> + <? $i++ ?> + <? endforeach ?> + </table> + <input type="submit" value="<?= t("Change")->for_html_attr() ?>" /> + </form> +</div> diff --git a/modules/gallery/views/admin_identity_confirm.html.php b/modules/gallery/views/admin_identity_confirm.html.php new file mode 100644 index 00000000..e14525b5 --- /dev/null +++ b/modules/gallery/views/admin_identity_confirm.html.php @@ -0,0 +1,10 @@ +<?php defined("SYSPATH") or die("No direct script access.") ?> +<form method="post" action="<?= url::site("admin/identity/change") ?>"> + <?= access::csrf_form_field() ?> + <?= form::hidden("provider", $new_provider) ?> + + <p><span class="ui-icon ui-icon-alert" style="float: left; margin:0 7px 20px 0;"></span> + <?= t("Do you really want to switch Identity providers? Continuing will delete all existing users.") ?> + </p> +</form> + diff --git a/modules/gallery/views/kohana_error_page.php b/modules/gallery/views/kohana_error_page.php index 314a9923..0256fabb 100644 --- a/modules/gallery/views/kohana_error_page.php +++ b/modules/gallery/views/kohana_error_page.php @@ -57,7 +57,7 @@ <title><?= t("Something went wrong!") ?></title> </head> <body> - <? try { $user = user::active(); } catch (Exception $e) { } ?> + <? try { $user = Session::active_user(); } catch (Exception $e) { } ?> <? $admin = php_sapi_name() == "cli" || isset($user) && $user->admin ?> <div class="big_box" id="framework_error"> <h1> diff --git a/modules/gallery/views/login.html.php b/modules/gallery/views/login.html.php index 9be218c0..6695d564 100644 --- a/modules/gallery/views/login.html.php +++ b/modules/gallery/views/login.html.php @@ -8,11 +8,15 @@ </li> <? else: ?> <li class="first"> + <? if (Identity::is_writable()): ?> <?= t('Logged in as %name', array('name' => html::mark_clean( '<a href="' . url::site("form/edit/users/{$user->id}") . '" title="' . t("Edit Your Profile")->for_html_attr() . '" id="g-user-profile-link" class="g-dialog-link">' . html::clean($user->display_name()) . '</a>'))) ?> + <? else: ?> + <?= t('Logged in as %name', array('name' => html::clean($user->display_name()))) ?> + <? endif ?> </li> <li> <a href="<?= url::site("logout?csrf=$csrf&continue=" . urlencode(url::current(true))) ?>" diff --git a/modules/gallery/views/login_ajax.html.php b/modules/gallery/views/login_ajax.html.php index d3364b46..6ed40571 100644 --- a/modules/gallery/views/login_ajax.html.php +++ b/modules/gallery/views/login_ajax.html.php @@ -36,8 +36,10 @@ <li id="g-login-form"> <?= $form ?> </li> + <? if (Identity::is_writable()): ?> <li> <a href="#" id="g-password-reset" class="g-right g-txt-small"><?= t("Forgot Your Password?") ?></a> </li> + <? endif ?> </ul> </div> diff --git a/modules/gallery/views/maintenance.html.php b/modules/gallery/views/maintenance.html.php index f80b6e7a..0aeaaec2 100644 --- a/modules/gallery/views/maintenance.html.php +++ b/modules/gallery/views/maintenance.html.php @@ -43,7 +43,7 @@ <p> <?= t("This site is currently only accessible by site administrators.") ?> </p> - <?= user::get_login_form("login/auth_html") ?> + <?= login::get_login_form("login/auth_html") ?> </body> </html> diff --git a/modules/notification/helpers/notification.php b/modules/notification/helpers/notification.php index 150616ab..080f154b 100644 --- a/modules/notification/helpers/notification.php +++ b/modules/notification/helpers/notification.php @@ -20,7 +20,7 @@ class notification { static function get_subscription($item_id, $user=null) { if (empty($user)) { - $user = user::active(); + $user = Session::active_user(); } return ORM::factory("subscription") @@ -31,7 +31,7 @@ class notification { static function is_watching($item, $user=null) { if (empty($user)) { - $user = user::active(); + $user = Session::active_user(); } return ORM::factory("subscription") @@ -44,7 +44,7 @@ class notification { static function add_watch($item, $user=null) { if ($item->is_album()) { if (empty($user)) { - $user = user::active(); + $user = Session::active_user(); } $subscription = ORM::factory("subscription"); $subscription->item_id = $item->id; @@ -56,7 +56,7 @@ class notification { static function remove_watch($item, $user=null) { if ($item->is_album()) { if (empty($user)) { - $user = user::active(); + $user = Session::active_user(); } $subscription = ORM::factory("subscription") @@ -67,8 +67,7 @@ class notification { } static function get_subscribers($item) { - // @todo only return distinct email addresses - $subscriber_ids = array(); + $subscriber_ids = array(); foreach (ORM::factory("subscription") ->select("user_id") ->join("items", "subscriptions.item_id", "items.id") @@ -79,12 +78,14 @@ class notification { $subscriber_ids[] = $subscriber->user_id; } - $users = user::get_user_list(array("in" => array("id", $subscriber_ids), - "where" => array("email IS NOT" => null))); + if (empty($subscriber_ids)) { + return array(); + } + $users = Identity::get_user_list($subscriber_ids); $subscribers = array(); foreach ($users as $user) { - if (access::user_can($user, "view", $item)) { + if (access::user_can($user, "view", $item) && !empty($user->email)) { $subscribers[$user->email] = 1; } } diff --git a/modules/notification/helpers/notification_event.php b/modules/notification/helpers/notification_event.php index 06c5bc44..f0530cd9 100644 --- a/modules/notification/helpers/notification_event.php +++ b/modules/notification/helpers/notification_event.php @@ -95,7 +95,7 @@ class notification_event_Core { } static function site_menu($menu, $theme) { - if (!user::active()->guest) { + if (!Session::active_user()->guest) { $item = $theme->item(); if ($item && $item->is_album() && access::can("view", $item)) { diff --git a/modules/search/helpers/search.php b/modules/search/helpers/search.php index 069b5b77..8b14cfa9 100644 --- a/modules/search/helpers/search.php +++ b/modules/search/helpers/search.php @@ -22,8 +22,8 @@ class search_Core { $db = Database::instance(); $q = $db->escape_str($q); - if (!user::active()->admin) { - foreach (user::group_ids() as $id) { + if (!Session::active_user()->admin) { + foreach (Session::group_ids_for_active_user() as $id) { $fields[] = "`view_$id` = TRUE"; // access::ALLOW } $access_sql = "AND (" . join(" AND ", $fields) . ")"; diff --git a/modules/server_add/controllers/server_add.php b/modules/server_add/controllers/server_add.php index 9769cd6f..428065f6 100644 --- a/modules/server_add/controllers/server_add.php +++ b/modules/server_add/controllers/server_add.php @@ -103,7 +103,7 @@ class Server_Add_Controller extends Admin_Controller { access::verify_csrf(); $task = ORM::factory("task", $task_id); - if (!$task->loaded || $task->owner_id != user::active()->id) { + if (!$task->loaded || $task->owner_id != Session::active_user()->id) { access::forbidden(); } @@ -207,7 +207,7 @@ class Server_Add_Controller extends Admin_Controller { $task->set("mode", "done"); } - $owner_id = user::active()->id; + $owner_id = Session::active_user()->id; foreach ($entries as $entry) { if (microtime(true) - $start > 0.5) { break; diff --git a/modules/server_add/helpers/server_add_event.php b/modules/server_add/helpers/server_add_event.php index 4db83f74..8f8b0016 100644 --- a/modules/server_add/helpers/server_add_event.php +++ b/modules/server_add/helpers/server_add_event.php @@ -30,7 +30,7 @@ class server_add_event_Core { $item = $theme->item(); $paths = unserialize(module::get_var("server_add", "authorized_paths")); - if ($item && user::active()->admin && $item->is_album() && !empty($paths) && + if ($item && Session::active_user()->admin && $item->is_album() && !empty($paths) && is_writable($item->is_album() ? $item->file_path() : $item->parent()->file_path())) { $menu->get("add_menu") ->append(Menu::factory("dialog") diff --git a/modules/server_add/helpers/server_add_theme.php b/modules/server_add/helpers/server_add_theme.php index 2ba2e167..44681d36 100644 --- a/modules/server_add/helpers/server_add_theme.php +++ b/modules/server_add/helpers/server_add_theme.php @@ -19,7 +19,7 @@ */ class server_add_theme_Core { static function head($theme) { - if (user::active()->admin) { + if (Session::active_user()->admin) { $theme->script("server_add.js"); } } diff --git a/modules/user/config/identity.php b/modules/user/config/identity.php new file mode 100644 index 00000000..f9f013aa --- /dev/null +++ b/modules/user/config/identity.php @@ -0,0 +1,37 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2009 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +/* + * @package Identity + * + * User settings, defined as arrays, or "groups". If no group name is + * used when loading the cache library, the group named "default" will be used. + * + * Each group can be used independently, and multiple groups can be used at once. + * + * Group Options: + * driver - User backend driver. Gallery comes with Gallery user driver. + * allow_updates - Flag to indicate that the back end allows updates. + * params - Driver parameters, specific to each driver. + */ +$config["user"] = array ( + "driver" => "gallery", + "allow_updates" => true, + "params" => array(), +); diff --git a/modules/user/controllers/admin_users.php b/modules/user/controllers/admin_users.php index 5950c358..258de843 100644 --- a/modules/user/controllers/admin_users.php +++ b/modules/user/controllers/admin_users.php @@ -21,8 +21,12 @@ class Admin_Users_Controller extends Admin_Controller { public function index() { $view = new Admin_View("admin.html"); $view->content = new View("admin_users.html"); - $view->content->users = user::get_user_list(array("orderby" => array("name" => "ASC"))); - $view->content->groups = group::get_group_list(array("orderby" => array("name" => "ASC"))); + $view->content->users = ORM::factory("user") + ->orderby("name", "ASC") + ->find_all(); + $view->content->groups = ORM::factory("group") + ->orderby("name", "ASC") + ->find_all(); print $view; } @@ -65,7 +69,7 @@ class Admin_Users_Controller extends Admin_Controller { public function delete_user($id) { access::verify_csrf(); - if ($id == user::active()->id || $id == user::guest()->id) { + if ($id == Session::active_user()->id || $id == user::guest()->id) { access::forbidden(); } @@ -132,7 +136,7 @@ class Admin_Users_Controller extends Admin_Controller { } // An admin can change the admin status for any user but themselves - if ($user->id != user::active()->id) { + if ($user->id != Session::active_user()->id) { $user->admin = $form->edit_user->admin->checked; } $user->save(); @@ -154,7 +158,7 @@ class Admin_Users_Controller extends Admin_Controller { $form = $this->_get_user_edit_form_admin($user); // Don't allow the user to control their own admin bit, else you can lock yourself out - if ($user->id == user::active()->id) { + if ($user->id == Session::active_user()->id) { $form->edit_user->admin->disabled(1); } print $form; @@ -325,8 +329,7 @@ class Admin_Users_Controller extends Admin_Controller { $group->input("url")->label(t("URL"))->id("g-url"); self::_add_locale_dropdown($group); $group->checkbox("admin")->label(t("Admin"))->id("g-admin"); - $user = ORM::factory("user"); - $form->add_rules_from($user); + $form->add_rules_from(ORM::factory("user")); module::event("user_add_form_admin", $user, $form); $group->submit("")->value(t("Add User")); @@ -378,8 +381,7 @@ class Admin_Users_Controller extends Admin_Controller { $form_group->inputs["name"]->error_messages( "in_use", t("There is already a group with that name")); $form_group->submit("")->value(t("Add Group")); - $group = ORM::factory("group"); - $form->add_rules_from($group); + $form->add_rules_from(ORM::factory("group")); return $form; } diff --git a/modules/gallery/controllers/password.php b/modules/user/controllers/password.php index e8b08960..a8f1c5ca 100644 --- a/modules/gallery/controllers/password.php +++ b/modules/user/controllers/password.php @@ -32,7 +32,7 @@ class Password_Controller extends Controller { if (request::method() == "post") { $this->_change_password(); } else { - $user = user::lookup_by_hash(Input::instance()->get("key")); + $user = user::lookup_user_by_field("hash", Input::instance()->get("key")); if (!empty($user)) { print $this->_new_password_form($user->hash); } else { @@ -46,7 +46,7 @@ class Password_Controller extends Controller { $valid = $form->validate(); if ($valid) { - $user = user::lockup_by_name($form->reset->inputs["name"]->value); + $user = Identity::lookup_user_by_name($form->reset->inputs["name"]->value); if (!$user->loaded || empty($user->email)) { $form->reset->inputs["name"]->add_error("no_email", 1); $valid = false; @@ -116,7 +116,7 @@ class Password_Controller extends Controller { private function _change_password() { $view = $this->_new_password_form(); if ($view->content->validate()) { - $user = user::lookup_by_hash(Input::instance()->get("key")); + $user = user::lookup_user_by_field("hash", Input::instance()->get("key")); if (empty($user)) { throw new Exception("@todo FORBIDDEN", 503); } diff --git a/modules/user/controllers/users.php b/modules/user/controllers/users.php index b03a47cc..0ccf3e2a 100644 --- a/modules/user/controllers/users.php +++ b/modules/user/controllers/users.php @@ -21,7 +21,7 @@ class Users_Controller extends Controller { public function update($id) { $user = user::lookup($id); - if ($user->guest || $user->id != user::active()->id) { + if ($user->guest || $user->id != Session::active_user()->id) { access::forbidden(); } @@ -59,7 +59,7 @@ class Users_Controller extends Controller { public function form_edit($id) { $user = user::lookup($id); - if ($user->guest || $user->id != user::active()->id) { + if ($user->guest || $user->id != Session::active_user()->id) { access::forbidden(); } diff --git a/modules/gallery/helpers/group.php b/modules/user/helpers/group.php index 1702fb87..8ad52564 100644 --- a/modules/gallery/helpers/group.php +++ b/modules/user/helpers/group.php @@ -25,10 +25,7 @@ */ class group_Core { /** - * Create a new group. - * - * @param string $name - * @return Group_Model + * @see Identity_Driver::create. */ static function create($name) { $group = ORM::factory("group")->where("name", $name)->find(); @@ -38,53 +35,45 @@ class group_Core { $group->name = $name; $group->save(); - return $group; } /** - * The group of all possible visitors. This includes the guest user. - * - * @return Group_Model + * @see Identity_Driver::everbody. */ static function everybody() { return model_cache::get("group", 1); } /** - * The group of all logged-in visitors. This does not include guest users. - * - * @return Group_Model + * @see Identity_Driver::registered_users. */ static function registered_users() { return model_cache::get("group", 2); } /** - * Look up a user by id. + * Look up a group by id. * @param integer $id the user id - * @return User_Model the user object, or null if the id was invalid. + * @return Group_Definition the group object, or null if the id was invalid. */ static function lookup($id) { - return self::_lookup_group_by_field("id", $id); + return self::lookup_by_field("id", $id); } /** * Look up a group by name. * @param integer $id the group name - * @return Group_Model the group object, or null if the name was invalid. + * @return Group_Definition the group object, or null if the name was invalid. */ static function lookup_by_name($name) { - return self::_lookup_group_by_field("name", $name); + return self::lookup_by_field("name", $name); } /** - * Look up a user by field value. - * @param string search field - * @param string search value - * @return Group_Model the user object, or null if the name was invalid. + * @see Identity_Driver::get_group_list. */ - private static function _lookup_group_by_field($field_name, $value) { + static function lookup_by_field($field_name, $value) { try { $user = model_cache::get("group", $value, $field_name); if ($user->loaded) { @@ -97,24 +86,4 @@ class group_Core { } return null; } - - /** - * List the users - * @param mixed filters (@see Database.php - * @return array the group list. - */ - static function get_group_list($filter=array()) { - $group = ORM::factory("group"); - - foreach($filter as $method => $args) { - switch ($method) { - case "in": - $group->in($args[0], $args[1]); - break; - default: - $group->$method($args); - } - } - return $group->find_all(); - } } diff --git a/modules/user/helpers/user.php b/modules/user/helpers/user.php new file mode 100644 index 00000000..ec4f56ae --- /dev/null +++ b/modules/user/helpers/user.php @@ -0,0 +1,189 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2009 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * This is the API for handling users. + * + * Note: by design, this class does not do any permission checking. + */ +class user_Core { + /** + * Initialize the provider so it is ready to use + */ + public function activate() { + $db = Database::instance(); + $db->query("CREATE TABLE IF NOT EXISTS {users} ( + `id` int(9) NOT NULL auto_increment, + `name` varchar(32) NOT NULL, + `full_name` varchar(255) NOT NULL, + `password` varchar(64) NOT NULL, + `login_count` int(10) unsigned NOT NULL DEFAULT 0, + `last_login` int(10) unsigned NOT NULL DEFAULT 0, + `email` varchar(64) default NULL, + `admin` BOOLEAN default 0, + `guest` BOOLEAN default 0, + `hash` char(32) default NULL, + `url` varchar(255) default NULL, + `locale` char(10) default NULL, + PRIMARY KEY (`id`), + UNIQUE KEY(`hash`), + UNIQUE KEY(`name`)) + DEFAULT CHARSET=utf8;"); + + $db->query("CREATE TABLE IF NOT EXISTS {groups} ( + `id` int(9) NOT NULL auto_increment, + `name` char(64) default NULL, + `special` BOOLEAN default 0, + PRIMARY KEY (`id`), + UNIQUE KEY(`name`)) + DEFAULT CHARSET=utf8;"); + + $db->query("CREATE TABLE IF NOT EXISTS {groups_users} ( + `group_id` int(9) NOT NULL, + `user_id` int(9) NOT NULL, + PRIMARY KEY (`group_id`, `user_id`), + UNIQUE KEY(`user_id`, `group_id`)) + DEFAULT CHARSET=utf8;"); + + $everybody = group::create("Everybody"); + $everybody->special = true; + $everybody->save(); + + $registered = group::create("Registered Users"); + $registered->special = true; + $registered->save(); + + $guest = user::create("guest", "Guest User", ""); + $guest->guest = true; + $guest->remove($registered); + $guest->save(); + + $admin = user::create("admin", "Gallery Administrator", "admin"); + $admin->admin = true; + $admin->save(); + + // Let the admin own everything + $db->query("update {items} set owner_id = {$admin->id}"); + + $root = ORM::factory("item", 1); + access::allow($everybody, "view", $root); + access::allow($everybody, "view_full", $root); + + access::allow($registered, "view", $root); + access::allow($registered, "view_full", $root); + } + + /** + * Cleanup up this provider so it is unavailable for use and won't conflict with the current driver + */ + public function deactivate() { + // Delete all users and groups so that we give other modules an opportunity to clean up + foreach (ORM::factory("user")->find_all() as $user) { + $user->delete(); + } + + foreach (ORM::factory("group")->find_all() as $group) { + $group->delete(); + } + + $db = Database::instance(); + $db->query("DROP TABLE IF EXISTS {users};"); + $db->query("DROP TABLE IF EXISTS {groups};"); + $db->query("DROP TABLE IF EXISTS {groups_users};"); + } + + /** + * Return the guest user. + * + * @return User_Model the user object + */ + static function guest() { + return model_cache::get("user", 1); + } + + /** + * Create a new user. + * + * @param string $name + * @param string $full_name + * @param string $password + * @return User_Definition the user object + */ + static function create($name, $full_name, $password) { + $user = ORM::factory("user")->where("name", $name)->find(); + if ($user->loaded) { + throw new Exception("@todo USER_ALREADY_EXISTS $name"); + } + + $user->name = $name; + $user->full_name = $full_name; + $user->password = $password; + + // Required groups + $user->add(group::everybody()); + $user->add(group::registered_users()); + + $user->save(); + return $user; + } + + /** + * Hash the password to the internal value + * @param string $password the user password + * @param string The hashed equivalent + */ + static function hash_password($password) { + require_once(MODPATH . "user/lib/PasswordHash.php"); + $hashGenerator = new PasswordHash(10, true); + return $hashGenerator->HashPassword($password); + } + + /** + * Look up a user by id. + * @param integer $id the user id + * @return User_Definition the user object, or null if the id was invalid. + */ + static function lookup($id) { + return self::lookup_by_field("id", $id); + } + + /** + * Look up a user by name. + * @param integer $name the user name + * @return User_Definition the user object, or null if the name was invalid. + */ + static function lookup_by_name($name) { + return self::lookup_by_field("name", $name); + } + + static function lookup_by_field($field_name, $value) { + try { + $user = model_cache::get("user", $value, $field_name); + if ($user->loaded) { + return $user; + } + } catch (Exception $e) { + if (strpos($e->getMessage(), "MISSING_MODEL") === false) { + throw $e; + } + } + return null; + } +}
\ No newline at end of file diff --git a/modules/user/helpers/user_event.php b/modules/user/helpers/user_event.php index 78b009eb..7916047f 100644 --- a/modules/user/helpers/user_event.php +++ b/modules/user/helpers/user_event.php @@ -20,11 +20,19 @@ class user_event_Core { static function admin_menu($menu, $theme) { - $menu->add_after("appearance_menu", - Menu::factory("link") - ->id("users_groups") - ->label(t("Users/Groups")) - ->url(url::site("admin/users"))); + $config = module::get_var("gallery", "identity_provider", "user"); + if ($config == "user") { + $user_group_menu = Menu::factory("link") + ->id("users_groups") + ->label(t("Users/Groups")) + ->url(url::site("admin/users")); + $identity_menu = $menu->get("identity_menu"); + if (empty($identity_menu)) { + $menu->add_after("appearance_menu", $user_group_menu); + }else { + $identity_menu->append($user_group_menu); + } + } return $menu; } } diff --git a/modules/user/helpers/user_installer.php b/modules/user/helpers/user_installer.php index 8ef4f13d..1410f1ef 100644 --- a/modules/user/helpers/user_installer.php +++ b/modules/user/helpers/user_installer.php @@ -19,87 +19,18 @@ */ class user_installer { static function install() { - $db = Database::instance(); - $db->query("CREATE TABLE IF NOT EXISTS {users} ( - `id` int(9) NOT NULL auto_increment, - `name` varchar(32) NOT NULL, - `full_name` varchar(255) NOT NULL, - `password` varchar(64) NOT NULL, - `login_count` int(10) unsigned NOT NULL DEFAULT 0, - `last_login` int(10) unsigned NOT NULL DEFAULT 0, - `email` varchar(64) default NULL, - `admin` BOOLEAN default 0, - `guest` BOOLEAN default 0, - `hash` char(32) default NULL, - `url` varchar(255) default NULL, - `locale` char(10) default NULL, - PRIMARY KEY (`id`), - UNIQUE KEY(`hash`), - UNIQUE KEY(`name`)) - DEFAULT CHARSET=utf8;"); - - $db->query("CREATE TABLE IF NOT EXISTS {groups} ( - `id` int(9) NOT NULL auto_increment, - `name` char(64) default NULL, - `special` BOOLEAN default 0, - PRIMARY KEY (`id`), - UNIQUE KEY(`name`)) - DEFAULT CHARSET=utf8;"); - - $db->query("CREATE TABLE IF NOT EXISTS {groups_users} ( - `group_id` int(9) NOT NULL, - `user_id` int(9) NOT NULL, - PRIMARY KEY (`group_id`, `user_id`), - UNIQUE KEY(`user_id`, `group_id`)) - DEFAULT CHARSET=utf8;"); - - $everybody = group::create("Everybody"); - $everybody->special = true; - $everybody->save(); - - $registered = group::create("Registered Users"); - $registered->special = true; - $registered->save(); - - $guest = user::create("guest", "Guest User", ""); - $guest->guest = true; - $guest->remove($registered); - $guest->save(); - - $admin = user::create("admin", "Gallery Administrator", "admin"); - $admin->admin = true; - $admin->save(); - - // Let the admin own everything - $db->update("items", array("owner_id" => $admin->id), array("owner_id" => "IS NULL")); + user::activate(); + module::set_var("gallery", "identity_provider", "user"); module::set_version("user", 1); - - $root = ORM::factory("item", 1); - access::allow($everybody, "view", $root); - access::allow($everybody, "view_full", $root); - - access::allow($registered, "view", $root); - access::allow($registered, "view_full", $root); } static function uninstall() { - // Delete all users and groups so that we give other modules an opportunity to clean up - foreach (ORM::factory("user")->find_all() as $user) { - $user->delete(); - } - - foreach (ORM::factory("group")->find_all() as $group) { - $group->delete(); - } + user::deactivate(); try { Session::instance()->destroy(); } catch (Exception $e) { // We don't care if there was a problem destroying the session. } - $db = Database::instance(); - $db->query("DROP TABLE IF EXISTS {users};"); - $db->query("DROP TABLE IF EXISTS {groups};"); - $db->query("DROP TABLE IF EXISTS {groups_users};"); } }
\ No newline at end of file diff --git a/modules/user/libraries/drivers/Identity/Gallery.php b/modules/user/libraries/drivers/Identity/Gallery.php new file mode 100644 index 00000000..36f37543 --- /dev/null +++ b/modules/user/libraries/drivers/Identity/Gallery.php @@ -0,0 +1,150 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2009 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. + */ +/* + * Based on the Cache_Sqlite_Driver developed by the Kohana Team + */ +class Identity_Gallery_Driver implements Identity_Driver { + /** + * @see Identity_Driver::activate. + */ + public function activate() { + user::activate(); + } + + /** + * @see Identity_Driver::deactivate. + */ + public function deactivate() { + user::deactivate(); + } + + /** + * @see Identity_Driver::guest. + */ + public function guest() { + return user::guest(); + } + + /** + * @see Identity_Driver::create_user. + */ + public function create_user($name, $full_name, $password) { + return user::create($name, $full_name, $password); + } + + /** + * @see Identity_Driver::is_correct_password. + */ + public function is_correct_password($user, $password) { + $valid = $user->password; + + // Try phpass first, since that's what we generate. + if (strlen($valid) == 34) { + require_once(MODPATH . "user/lib/PasswordHash.php"); + $hashGenerator = new PasswordHash(10, true); + return $hashGenerator->CheckPassword($password, $valid); + } + + $salt = substr($valid, 0, 4); + // Support both old (G1 thru 1.4.0; G2 thru alpha-4) and new password schemes: + $guess = (strlen($valid) == 32) ? md5($password) : ($salt . md5($salt . $password)); + if (!strcmp($guess, $valid)) { + return true; + } + + // Passwords with <&"> created by G2 prior to 2.1 were hashed with entities + $sanitizedPassword = html::specialchars($password, false); + $guess = (strlen($valid) == 32) ? md5($sanitizedPassword) + : ($salt . md5($salt . $sanitizedPassword)); + if (!strcmp($guess, $valid)) { + return true; + } + + return false; + } + + /** + * @see Identity_Driver::lookup_user. + */ + public function lookup_user($id) { + return user::lookup_by_field("id", $id); + } + + /** + * @see Identity_Driver::lookup_user_by_name. + */ + public function lookup_user_by_name($name) { + return user::lookup_by_field("name", $name); + } + + /** + * @see Identity_Driver::create_group. + */ + public function create_group($name) { + return group::create($name); + } + + /** + * @see Identity_Driver::everybody. + */ + public function everybody() { + return group::everybody(); + } + + /** + * @see Identity_Driver::registered_users. + */ + public function registered_users() { + return group::registered_users(); + } + + /** + * @see Identity_Driver::lookup_group. + */ + public function lookup_group($id) { + return group::lookup_by_field("id", $id); + } + + /** + * @see Identity_Driver::lookup_group_by_name. + */ + public function lookup_group_by_name($name) { + return group::lookup_by_field("name", $name); + } + + /** + * @see Identity_Driver::get_user_list. + */ + public function get_user_list($ids) { + return ORM::factory("user") + ->in("id", $ids) + ->find_all() + ->as_array(); + } + + /** + * @see Identity_Driver::groups. + */ + public function groups() { + return ORM::factory("group")->find_all(); + } + +} // End Identity Gallery Driver + diff --git a/modules/user/models/group.php b/modules/user/models/group.php index 8af78012..4432fc69 100644 --- a/modules/user/models/group.php +++ b/modules/user/models/group.php @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -class Group_Model extends ORM { +class Group_Model extends ORM implements Group_Definition { protected $has_and_belongs_to_many = array("users"); var $rules = array( diff --git a/modules/user/models/user.php b/modules/user/models/user.php index 55562f34..c51fc720 100644 --- a/modules/user/models/user.php +++ b/modules/user/models/user.php @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -class User_Model extends ORM { +class User_Model extends ORM implements User_Definition { protected $has_and_belongs_to_many = array("groups"); var $rules = array( @@ -82,4 +82,4 @@ class User_Model extends ORM { public function display_name() { return empty($this->full_name) ? $this->name : $this->full_name; } -}
\ No newline at end of file +} diff --git a/modules/user/views/admin_users.html.php b/modules/user/views/admin_users.html.php index aae39c8c..ee8d413c 100644 --- a/modules/user/views/admin_users.html.php +++ b/modules/user/views/admin_users.html.php @@ -2,7 +2,7 @@ <script type="text/javascript"> var add_user_to_group_url = "<?= url::site("admin/users/add_user_to_group/__USERID__/__GROUPID__?csrf=$csrf") ?>"; $(document).ready(function(){ - $("#g-user-admin-list .core-info").draggable({ + $("#g-user-admin-list .g-draggable").draggable({ helper: "clone" }); $("#g-group-admin .g-group").droppable({ @@ -20,6 +20,7 @@ }); $("#group-1").droppable("destroy"); $("#group-2").droppable("destroy"); + $(".g-group-disable").droppable("destroy"); }); var reload_group = function(group_id) { @@ -90,7 +91,7 @@ open_text="<?= t("close") ?>" class="g-panel-link g-button ui-state-default ui-corner-all ui-icon-left"> <span class="ui-icon ui-icon-pencil"></span><span class="g-button-text"><?= t("edit") ?></span></a> - <? if (user::active()->id != $user->id && !$user->guest): ?> + <? if (Session::active_user()->id != $user->id && !$user->guest): ?> <a href="<?= url::site("admin/users/delete_user_form/$user->id") ?>" class="g-dialog-link g-button ui-state-default ui-corner-all ui-icon-left"> <span class="ui-icon ui-icon-trash"></span><?= t("delete") ?></a> diff --git a/modules/gallery/views/reset_password.html.php b/modules/user/views/reset_password.html.php index 92ca4917..92ca4917 100644 --- a/modules/gallery/views/reset_password.html.php +++ b/modules/user/views/reset_password.html.php diff --git a/themes/admin_wind/css/screen.css b/themes/admin_wind/css/screen.css index a889545b..65a2f43b 100644 --- a/themes/admin_wind/css/screen.css +++ b/themes/admin_wind/css/screen.css @@ -418,7 +418,8 @@ li.g-group .g-user .g-button { vertical-align: middle; } -li.g-default-group h4, li.g-default-group .g-user { +li.g-default-group h4, li.g-default-group .g-user, +li.g-group-disable h4, li.g-group-disable .g-user { color: gray; } |