diff options
Diffstat (limited to 'modules/user')
25 files changed, 867 insertions, 695 deletions
diff --git a/modules/user/controllers/logout.php b/modules/user/config/identity.php index 45d397ad..f9f013aa 100644 --- a/modules/user/controllers/logout.php +++ b/modules/user/config/identity.php @@ -17,22 +17,21 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -class Logout_Controller extends Controller { - public function index() { - //access::verify_csrf(); - - $user = user::active(); - user::logout(); - 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")) { - $item = url::get_item_from_uri($continue_url); - if (access::can("view", $item)) { - // Don't use url::redirect() because it'll call url::site() and munge the continue url. - header("Location: $continue_url"); - } else { - url::redirect(item::root()->abs_url()); - } - } - } -}
\ No newline at end of file +/* + * @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 0b748955..cc2d881e 100644 --- a/modules/user/controllers/admin_users.php +++ b/modules/user/controllers/admin_users.php @@ -21,19 +21,22 @@ 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 = ORM::factory("user")->orderby("name")->find_all(); - $view->content->groups = ORM::factory("group")->orderby("name")->find_all(); + $view->content->users = ORM::factory("user") + ->orderby("name", "ASC") + ->find_all(); + $view->content->groups = ORM::factory("group") + ->orderby("name", "ASC") + ->find_all(); print $view; } public function add_user() { access::verify_csrf(); - $form = user::get_add_form_admin(); + $form = $this->_get_user_add_form_admin(); $valid = $form->validate(); $name = $form->add_user->inputs["name"]->value; - $user = ORM::factory("user")->where("name", $name)->find(); - if ($user->loaded) { + if ($user = user::lookup_by_name($name)) { $form->add_user->inputs["name"]->add_error("in_use", 1); $valid = false; } @@ -60,22 +63,24 @@ class Admin_Users_Controller extends Admin_Controller { } public function add_user_form() { - print user::get_add_form_admin(); + $v = new View("user_form.html"); + $v->form = $this->_get_user_add_form_admin(); + print $v; } public function delete_user($id) { access::verify_csrf(); - if ($id == user::active()->id || $id == user::guest()->id) { + if ($id == identity::active_user()->id || $id == user::guest()->id) { access::forbidden(); } - $user = ORM::factory("user", $id); - if (!$user->loaded) { + $user = user::lookup($id); + if (empty($user)) { kohana::show_404(); } - $form = user::get_delete_form_admin($user); + $form = $this->_get_user_delete_form_admin($user); if($form->validate()) { $name = $user->name; $user->delete(); @@ -91,31 +96,28 @@ class Admin_Users_Controller extends Admin_Controller { } public function delete_user_form($id) { - $user = ORM::factory("user", $id); - if (!$user->loaded) { + $user = user::lookup($id); + if (empty($user)) { kohana::show_404(); } - print user::get_delete_form_admin($user); + print $this->_get_user_delete_form_admin($user); } public function edit_user($id) { access::verify_csrf(); - $user = ORM::factory("user", $id); - if (!$user->loaded) { + $user = user::lookup($id); + if (empty($user)) { kohana::show_404(); } - $form = user::get_edit_form_admin($user); + $form = $this->_get_user_edit_form_admin($user); $valid = $form->validate(); if ($valid) { $new_name = $form->edit_user->inputs["name"]->value; + $temp_user = user::lookup_by_name($new_name); if ($new_name != $user->name && - ORM::factory("user") - ->where("name", $new_name) - ->where("id !=", $user->id) - ->find() - ->loaded) { + ($temp_user && $temp_user->id != $user->id)) { $form->edit_user->inputs["name"]->add_error("in_use", 1); $valid = false; } else { @@ -136,7 +138,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 != identity::active_user()->id) { $user->admin = $form->edit_user->admin->checked; } $user->save(); @@ -151,50 +153,51 @@ class Admin_Users_Controller extends Admin_Controller { } public function edit_user_form($id) { - $user = ORM::factory("user", $id); - if (!$user->loaded) { + $user = user::lookup($id); + if (empty($user)) { kohana::show_404(); } - $form = user::get_edit_form_admin($user); + $v = new View("user_form.html"); + $v->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) { - $form->edit_user->admin->disabled(1); + if ($user->id == identity::active_user()->id) { + $v->form->edit_user->admin->disabled(1); } - print $form; + print $v; } public function add_user_to_group($user_id, $group_id) { access::verify_csrf(); - $group = ORM::factory("group", $group_id); - $user = ORM::factory("user", $user_id); + $group = group::lookup($group_id); + $user = user::lookup($user_id); $group->add($user); $group->save(); } public function remove_user_from_group($user_id, $group_id) { access::verify_csrf(); - $group = ORM::factory("group", $group_id); - $user = ORM::factory("user", $user_id); + $group = group::lookup($group_id); + $user = user::lookup($user_id); $group->remove($user); $group->save(); } public function group($group_id) { $view = new View("admin_users_group.html"); - $view->group = ORM::factory("group", $group_id); + $view->group = group::lookup($group_id); print $view; } public function add_group() { access::verify_csrf(); - $form = group::get_add_form_admin(); + $form = $this->_get_group_add_form_admin(); $valid = $form->validate(); if ($valid) { $new_name = $form->add_group->inputs["name"]->value; - $group = ORM::factory("group")->where("name", $new_name)->find(); - if ($group->loaded) { + $group = group::lookup_by_name($new_name); + if (!empty($group)) { $form->add_group->inputs["name"]->add_error("in_use", 1); $valid = false; } @@ -213,18 +216,18 @@ class Admin_Users_Controller extends Admin_Controller { } public function add_group_form() { - print group::get_add_form_admin(); + print $this->_get_group_add_form_admin(); } public function delete_group($id) { access::verify_csrf(); - $group = ORM::factory("group", $id); - if (!$group->loaded) { + $group = group::lookup($id); + if (empty($group)) { kohana::show_404(); } - $form = group::get_delete_form_admin($group); + $form = $this->_get_group_delete_form_admin($group); if ($form->validate()) { $name = $group->name; $group->delete(); @@ -240,27 +243,28 @@ class Admin_Users_Controller extends Admin_Controller { } public function delete_group_form($id) { - $group = ORM::factory("group", $id); - if (!$group->loaded) { + $group = group::lookup($id); + if (empty($group)) { kohana::show_404(); } - print group::get_delete_form_admin($group); + + print $this->_get_group_delete_form_admin($group); } public function edit_group($id) { access::verify_csrf(); - $group = ORM::factory("group", $id); - if (!$group->loaded) { - kohana::show_404(); + $group = group::lookup($id); + if (empty($group)) { + kohana::show_404(); } - $form = group::get_edit_form_admin($group); + $form = $this->_get_group_edit_form_admin($group); $valid = $form->validate(); if ($valid) { $new_name = $form->edit_group->inputs["name"]->value; - $group = ORM::factory("group")->where("name", $new_name)->find(); + $group = group::lookup_by_name($name); if ($group->loaded) { $form->edit_group->inputs["name"]->add_error("in_use", 1); $valid = false; @@ -282,12 +286,118 @@ class Admin_Users_Controller extends Admin_Controller { } public function edit_group_form($id) { - $group = ORM::factory("group", $id); - if (!$group->loaded) { + $group = group::lookup($id); + if (empty($group)) { kohana::show_404(); } - print group::get_edit_form_admin($group); + print $this->_get_group_edit_form_admin($group); + } + + /* User Form Definitions */ + static function _get_user_edit_form_admin($user) { + $form = new Forge( + "admin/users/edit_user/$user->id", "", "post", array("id" => "g-edit-user-form")); + $group = $form->group("edit_user")->label(t("Edit user")); + $group->input("name")->label(t("Username"))->id("g-username")->value($user->name); + $group->inputs["name"]->error_messages( + "in_use", t("There is already a user with that username")); + $group->input("full_name")->label(t("Full name"))->id("g-fullname")->value($user->full_name); + self::_add_locale_dropdown($group, $user); + $group->password("password")->label(t("Password"))->id("g-password"); + $group->password("password2")->label(t("Confirm password"))->id("g-password2") + ->matches($group->password); + $group->input("email")->label(t("Email"))->id("g-email")->value($user->email); + $group->input("url")->label(t("URL"))->id("g-url")->value($user->url); + $group->checkbox("admin")->label(t("Admin"))->id("g-admin")->checked($user->admin); + $form->add_rules_from($user); + $minimum_length = module::get_var("user", "mininum_password_length", 5); + $form->edit_user->password + ->rules($minimum_length ? "length[$minimum_length, 40]" : "length[40]"); + + module::event("user_edit_form_admin", $user, $form); + $group->submit("")->value(t("Modify User")); + return $form; + } + + static function _get_user_add_form_admin() { + $form = new Forge("admin/users/add_user", "", "post", array("id" => "g-add-user-form")); + $group = $form->group("add_user")->label(t("Add user")); + $group->input("name")->label(t("Username"))->id("g-username") + ->error_messages("in_use", t("There is already a user with that username")); + $group->input("full_name")->label(t("Full name"))->id("g-fullname"); + $group->password("password")->label(t("Password"))->id("g-password"); + $group->password("password2")->label(t("Confirm password"))->id("g-password2") + ->matches($group->password); + $group->input("email")->label(t("Email"))->id("g-email"); + $group->input("url")->label(t("URL"))->id("g-url"); + self::_add_locale_dropdown($group); + $group->checkbox("admin")->label(t("Admin"))->id("g-admin"); + $form->add_rules_from(ORM::factory("user")); + + $minimum_length = module::get_var("user", "mininum_password_length", 5); + $form->add_user->password + ->rules($minimum_length ? "required|length[$minimum_length, 40]" : "length[40]"); + + module::event("user_add_form_admin", $user, $form); + $group->submit("")->value(t("Add User")); + return $form; + } + + private function _add_locale_dropdown(&$form, $user=null) { + $locales = locales::installed(); + foreach ($locales as $locale => $display_name) { + $locales[$locale] = SafeString::of_safe_html($display_name); + } + if (count($locales) > 1) { + // Put "none" at the first position in the array + $locales = array_merge(array("" => t("« none »")), $locales); + $selected_locale = ($user && $user->locale) ? $user->locale : ""; + $form->dropdown("locale") + ->label(t("Language Preference")) + ->options($locales) + ->selected($selected_locale); + } + } + + private function _get_user_delete_form_admin($user) { + $form = new Forge("admin/users/delete_user/$user->id", "", "post", + array("id" => "g-delete-user-form")); + $group = $form->group("delete_user")->label( + t("Are you sure you want to delete user %name?", array("name" => $user->name))); + $group->submit("")->value(t("Delete user %name", array("name" => $user->name))); + return $form; } + /* Group Form Definitions */ + private function _get_group_edit_form_admin($group) { + $form = new Forge("admin/users/edit_group/$group->id", "", "post", array("id" => "g-edit-group-form")); + $form_group = $form->group("edit_group")->label(t("Edit group")); + $form_group->input("name")->label(t("Name"))->id("g-name")->value($group->name); + $form_group->inputs["name"]->error_messages( + "in_use", t("There is already a group with that name")); + $form_group->submit("")->value(t("Save")); + $form->add_rules_from($group); + return $form; + } + + private function _get_group_add_form_admin() { + $form = new Forge("admin/users/add_group", "", "post", array("id" => "g-add-group-form")); + $form_group = $form->group("add_group")->label(t("Add group")); + $form_group->input("name")->label(t("Name"))->id("g-name"); + $form_group->inputs["name"]->error_messages( + "in_use", t("There is already a group with that name")); + $form_group->submit("")->value(t("Add group")); + $form->add_rules_from(ORM::factory("group")); + return $form; + } + + private function _get_group_delete_form_admin($group) { + $form = new Forge("admin/users/delete_group/$group->id", "", "post", + array("id" => "g-delete-group-form")); + $form_group = $form->group("delete_group")->label( + t("Are you sure you want to delete group %group_name?", array("group_name" => $group->name))); + $form_group->submit("")->value(t("Delete")); + return $form; + } } diff --git a/modules/user/controllers/login.php b/modules/user/controllers/login.php deleted file mode 100644 index 8bee7db5..00000000 --- a/modules/user/controllers/login.php +++ /dev/null @@ -1,82 +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. - */ -class Login_Controller extends Controller { - - public function ajax() { - $view = new View("login_ajax.html"); - $view->form = user::get_login_form("login/auth_ajax"); - print $view; - } - - public function auth_ajax() { - access::verify_csrf(); - - list ($valid, $form) = $this->_auth("login/auth_ajax"); - if ($valid) { - print json_encode( - array("result" => "success")); - } else { - print json_encode( - array("result" => "error", - "form" => $form->__toString())); - } - } - - public function html() { - print user::get_login_form("login/auth_html"); - } - - public function auth_html() { - access::verify_csrf(); - - list ($valid, $form) = $this->_auth("login/auth_html"); - if ($valid) { - url::redirect(item::root()->abs_url()); - } else { - print $form; - } - } - - private function _auth($url) { - $form = user::get_login_form($url); - $valid = $form->validate(); - if ($valid) { - $user = ORM::factory("user")->where("name", $form->login->inputs["name"]->value)->find(); - if (!$user->loaded || !user::is_correct_password($user, $form->login->password->value)) { - log::warning( - "user", - t("Failed login for %name", - array("name" => $form->login->inputs["name"]->value))); - $form->login->inputs["name"]->add_error("invalid_login", 1); - $valid = false; - } - } - - if ($valid) { - user::login($user); - log::info("user", t("User %name logged in", array("name" => $user->name))); - } - - // Either way, regenerate the session id to avoid session trapping - Session::instance()->regenerate(); - - return array($valid, $form); - } -}
\ No newline at end of file diff --git a/modules/user/controllers/password.php b/modules/user/controllers/password.php index 92608dcd..5f36b554 100644 --- a/modules/user/controllers/password.php +++ b/modules/user/controllers/password.php @@ -32,10 +32,8 @@ class Password_Controller extends Controller { if (request::method() == "post") { $this->_change_password(); } else { - $user = ORM::factory("user") - ->where("hash", Input::instance()->get("key")) - ->find(); - if ($user->loaded) { + $user = user::lookup_by_hash(Input::instance()->get("key")); + if (!empty($user)) { print $this->_new_password_form($user->hash); } else { throw new Exception("@todo FORBIDDEN", 503); @@ -48,7 +46,7 @@ class Password_Controller extends Controller { $valid = $form->validate(); if ($valid) { - $user = ORM::factory("user")->where("name", $form->reset->inputs["name"]->value)->find(); + $user = user::lookup_by_name($form->reset->inputs["name"]->value); if (!$user->loaded || empty($user->email)) { $form->reset->inputs["name"]->add_error("no_email", 1); $valid = false; @@ -85,9 +83,9 @@ class Password_Controller extends Controller { } private function _reset_form() { - $form = new Forge(url::current(true), "", "post", array("id" => "gResetForm")); + $form = new Forge(url::current(true), "", "post", array("id" => "g-reset-form")); $group = $form->group("reset")->label(t("Reset Password")); - $group->input("name")->label(t("Username"))->id("gName")->class(null)->rules("required"); + $group->input("name")->label(t("Username"))->id("g-name")->class(null)->rules("required"); $group->inputs["name"]->error_messages("no_email", t("No email, unable to reset password")); $group->submit("")->value(t("Reset")); @@ -97,36 +95,35 @@ class Password_Controller extends Controller { private function _new_password_form($hash=null) { $template = new Theme_View("page.html", "reset"); - $form = new Forge("password/do_reset", "", "post", array("id" => "gChangePasswordForm")); + $form = new Forge("password/do_reset", "", "post", array("id" => "g-change-password-form")); $group = $form->group("reset")->label(t("Change Password")); $hidden = $group->hidden("hash"); if (!empty($hash)) { $hidden->value($hash); } - $group->password("password")->label(t("Password"))->id("gPassword") - ->rules("required|length[1,40]"); - $group->password("password2")->label(t("Confirm Password"))->id("gPassword2") + $minimum_length = module::get_var("user", "mininum_password_length", 5); + $input_password = $group->password("password")->label(t("Password"))->id("g-password") + ->rules($minimum_length ? "required|length[$minimum_length, 40]" : "length[40]"); + $group->password("password2")->label(t("Confirm Password"))->id("g-password2") ->matches($group->password); $group->inputs["password2"]->error_messages( "mistyped", t("The password and the confirm password must match")); $group->submit("")->value(t("Update")); - $template->content = $form; + $template->content = new View("user_form.html"); + $template->content->form = $form; return $template; } private function _change_password() { $view = $this->_new_password_form(); - if ($view->content->validate()) { - $user = ORM::factory("user") - ->where("hash", $view->content->reset->hash->value) - ->find(); - - if (!$user->loaded) { + if ($view->content->form->validate()) { + $user = user::lookup_by_hash(Input::instance()->post("hash")); + if (empty($user)) { throw new Exception("@todo FORBIDDEN", 503); } - $user->password = $view->content->reset->password->value; + $user->password = $view->content->form->reset->password->value; $user->hash = null; $user->save(); message::success(t("Password reset successfully")); diff --git a/modules/user/controllers/users.php b/modules/user/controllers/users.php index 4ad704f0..ca218393 100644 --- a/modules/user/controllers/users.php +++ b/modules/user/controllers/users.php @@ -17,15 +17,15 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -class Users_Controller extends REST_Controller { - protected $resource_type = "user"; +class Users_Controller extends Controller { + public function update($id) { + $user = user::lookup($id); - public function _update($user) { - if ($user->guest || $user->id != user::active()->id) { + if ($user->guest || $user->id != identity::active_user()->id) { access::forbidden(); } - $form = user::get_edit_form($user); + $form = $this->_get_edit_form($user); $valid = $form->validate(); if ($valid) { $user->full_name = $form->edit_user->full_name->value; @@ -57,11 +57,52 @@ class Users_Controller extends REST_Controller { } } - public function _form_edit($user) { - if ($user->guest || $user->id != user::active()->id) { + public function form_edit($id) { + $user = user::lookup($id); + if ($user->guest || $user->id != identity::active_user()->id) { access::forbidden(); } - print user::get_edit_form($user); + $v = new View("user_form.html"); + $v->form = $this->_get_edit_form($user); + print $v; + } + + private function _get_edit_form($user) { + $form = new Forge("users/update/$user->id", "", "post", array("id" => "g-edit-user-form")); + $group = $form->group("edit_user")->label(t("Edit User: %name", array("name" => $user->name))); + $group->input("full_name")->label(t("Full Name"))->id("g-fullname")->value($user->full_name); + self::_add_locale_dropdown($group, $user); + $group->password("password")->label(t("Password"))->id("g-password"); + $group->password("password2")->label(t("Confirm Password"))->id("g-password2") + ->matches($group->password); + $group->input("email")->label(t("Email"))->id("g-email")->value($user->email); + $group->input("url")->label(t("URL"))->id("g-url")->value($user->url); + $form->add_rules_from($user); + + $minimum_length = module::get_var("user", "mininum_password_length", 5); + $form->edit_user->password + ->rules($minimum_length ? "length[$minimum_length, 40]" : "length[40]"); + + module::event("user_edit_form", $user, $form); + $group->submit("")->value(t("Save")); + return $form; + } + + /** @todo combine with Admin_Users_Controller::_add_locale_dropdown */ + private function _add_locale_dropdown(&$form, $user=null) { + $locales = locales::installed(); + foreach ($locales as $locale => $display_name) { + $locales[$locale] = SafeString::of_safe_html($display_name); + } + if (count($locales) > 1) { + // Put "none" at the first position in the array + $locales = array_merge(array("" => t("« none »")), $locales); + $selected_locale = ($user && $user->locale) ? $user->locale : ""; + $form->dropdown("locale") + ->label(t("Language Preference")) + ->options($locales) + ->selected($selected_locale); + } } } diff --git a/modules/user/css/user.css b/modules/user/css/user.css new file mode 100644 index 00000000..084eac31 --- /dev/null +++ b/modules/user/css/user.css @@ -0,0 +1,119 @@ +/* User- and group-related form width ~~~~ */ + +#g-login-form, +#g-add-user-form +#g-edit-user-form, +#g-delete-user-form, +#g-user-admin { + width: 270px; +} + +/* User/group admin ~~~~~~~~~~~~~~~~~~~~~~ */ + +#g-user-admin { + width: auto; +} + +#g-group-admin { +} + +#g-user-admin-list .g-admin { + color: #55f; + font-weight: bold; +} + +.g-group { + display: block; + border: 1px solid #999; + margin: 0 1em 1em 0; + padding: 0; + width: 200px; +} + +.g-group h4 { + background-color: #eee; + border-bottom: 1px dashed #ccc; + padding: .5em 0 .5em .5em; +} + +.g-group .g-button { + padding: 0; +} + +.g-group .g-member-list, +.g-group div { + height: 180px; + margin: 1px; + overflow: auto; +} + +.g-group p { + margin-top: 1em; + padding: .5em; + text-align: center; +} + +.g-group .g-user { + padding: .2em 0 0 .5em; +} + +.g-group .g-user .g-button { + vertical-align: middle; +} + +.g-default-group h4, +.g-default-group .g-user { + color: #999; +} + +.g-group.ui-droppable { + padding: 0 !important; +} + +/* Password strength meter ~~~~~~~~~~~~~~~ */ + +.g-password-strength0 { + background: url(../images/progressImg1.png) no-repeat 0 0; + width: 138px; + height: 7px; +} + +.g-password-strength10 { + background-position:0 -7px; +} + +.g-password-strength20 { + background-position:0 -14px; +} + +.g-password-strength30 { + background-position:0 -21px; +} + +.g-password-strength40 { + background-position:0 -28px; +} + +.g-password-strength50 { + background-position:0 -35px; +} + +.g-password-strength60 { + background-position:0 -42px; +} + +.g-password-strength70 { + background-position:0 -49px; +} + +.g-password-strength80 { + background-position:0 -56px; +} + +.g-password-strength90 { + background-position:0 -63px; +} + +.g-password-strength100 { + background-position:0 -70px; +} diff --git a/modules/user/helpers/group.php b/modules/user/helpers/group.php index 04e6efd6..3aaf1b11 100644 --- a/modules/user/helpers/group.php +++ b/modules/user/helpers/group.php @@ -28,7 +28,7 @@ class group_Core { * Create a new group. * * @param string $name - * @return Group_Model + * @return Group_Definition the group object */ static function create($name) { $group = ORM::factory("group")->where("name", $name)->find(); @@ -38,14 +38,13 @@ class group_Core { $group->name = $name; $group->save(); - return $group; } /** * The group of all possible visitors. This includes the guest user. * - * @return Group_Model + * @return Group_Definition the group object */ static function everybody() { return model_cache::get("group", 1); @@ -54,54 +53,47 @@ class group_Core { /** * The group of all logged-in visitors. This does not include guest users. * - * @return Group_Model + * @return Group_Definition the group object */ static function registered_users() { return model_cache::get("group", 2); } /** + * Look up a group by id. + * @param integer $id the user id + * @return Group_Definition the group object, or null if the id was invalid. + */ + static function lookup($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) { - $group = model_cache::get("group", $name, "name"); - if ($group->loaded) { - return $group; - } - return null; + return self::_lookup_by_field("name", $name); } - static function get_edit_form_admin($group) { - $form = new Forge("admin/users/edit_group/$group->id", "", "post", array("id" => "gEditGroupForm")); - $form_group = $form->group("edit_group")->label(t("Edit Group")); - $form_group->input("name")->label(t("Name"))->id("gName")->value($group->name); - $form_group->inputs["name"]->error_messages( - "in_use", t("There is already a group with that name")); - $form_group->submit("")->value(t("Save")); - $form->add_rules_from($group); - return $form; - } - - static function get_add_form_admin() { - $form = new Forge("admin/users/add_group", "", "post", array("id" => "gAddGroupForm")); - $form_group = $form->group("add_group")->label(t("Add Group")); - $form_group->input("name")->label(t("Name"))->id("gName"); - $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); - return $form; - } - - static function get_delete_form_admin($group) { - $form = new Forge("admin/users/delete_group/$group->id", "", "post", - array("id" => "gDeleteGroupForm")); - $form_group = $form->group("delete_group")->label( - t("Are you sure you want to delete group %group_name?", array("group_name" => $group->name))); - $form_group->submit("")->value(t("Delete")); - return $form; + /** + * Search the groups by the field and value. + * @param string $field_name column to look up the user by + * @param string $value value to match + * @return Group_Definition the group object, or null if the name was invalid. + */ + private static function _lookup_by_field($field_name, $value) { + try { + $user = model_cache::get("group", $value, $field_name); + if ($user->loaded) { + return $user; + } + } catch (Exception $e) { + if (strpos($e->getMessage(), "MISSING_MODEL") === false) { + throw $e; + } + } + return null; } } diff --git a/modules/user/helpers/user.php b/modules/user/helpers/user.php index b9162b92..f9f16da5 100644 --- a/modules/user/helpers/user.php +++ b/modules/user/helpers/user.php @@ -24,153 +24,6 @@ * Note: by design, this class does not do any permission checking. */ class user_Core { - static function get_edit_form($user) { - $form = new Forge("users/$user->id?_method=put", "", "post", array("id" => "gEditUserForm")); - $group = $form->group("edit_user")->label(t("Edit User: %name", array("name" => $user->name))); - $group->input("full_name")->label(t("Full Name"))->id("gFullName")->value($user->full_name); - self::_add_locale_dropdown($group, $user); - $group->password("password")->label(t("Password"))->id("gPassword"); - $group->password("password2")->label(t("Confirm Password"))->id("gPassword2") - ->matches($group->password); - $group->input("email")->label(t("Email"))->id("gEmail")->value($user->email); - $group->input("url")->label(t("URL"))->id("gUrl")->value($user->url); - $form->add_rules_from($user); - - module::event("user_edit_form", $user, $form); - $group->submit("")->value(t("Save")); - return $form; - } - - static function get_edit_form_admin($user) { - $form = new Forge( - "admin/users/edit_user/$user->id", "", "post", array("id" => "gEditUserForm")); - $group = $form->group("edit_user")->label(t("Edit User")); - $group->input("name")->label(t("Username"))->id("gUsername")->value($user->name); - $group->inputs["name"]->error_messages( - "in_use", t("There is already a user with that username")); - $group->input("full_name")->label(t("Full Name"))->id("gFullName")->value($user->full_name); - self::_add_locale_dropdown($group, $user); - $group->password("password")->label(t("Password"))->id("gPassword"); - $group->password("password2")->label(t("Confirm Password"))->id("gPassword2") - ->matches($group->password); - $group->input("email")->label(t("Email"))->id("gEmail")->value($user->email); - $group->input("url")->label(t("URL"))->id("gUrl")->value($user->url); - $group->checkbox("admin")->label(t("Admin"))->id("gAdmin")->checked($user->admin); - $form->add_rules_from($user); - $form->edit_user->password->rules("-required"); - - module::event("user_edit_form_admin", $user, $form); - $group->submit("")->value(t("Modify User")); - return $form; - } - - static function get_add_form_admin() { - $form = new Forge("admin/users/add_user", "", "post", array("id" => "gAddUserForm")); - $group = $form->group("add_user")->label(t("Add User")); - $group->input("name")->label(t("Username"))->id("gUsername") - ->error_messages("in_use", t("There is already a user with that username")); - $group->input("full_name")->label(t("Full Name"))->id("gFullName"); - $group->password("password")->label(t("Password"))->id("gPassword"); - $group->password("password2")->label(t("Confirm Password"))->id("gPassword2") - ->matches($group->password); - $group->input("email")->label(t("Email"))->id("gEmail"); - $group->input("url")->label(t("URL"))->id("gUrl"); - self::_add_locale_dropdown($group); - $group->checkbox("admin")->label(t("Admin"))->id("gAdmin"); - $user = ORM::factory("user"); - $form->add_rules_from($user); - - module::event("user_add_form_admin", $user, $form); - $group->submit("")->value(t("Add User")); - return $form; - } - - private static function _add_locale_dropdown(&$form, $user=null) { - $locales = locales::installed(); - foreach ($locales as $locale => $display_name) { - $locales[$locale] = SafeString::of_safe_html($display_name); - } - if (count($locales) > 1) { - // Put "none" at the first position in the array - $locales = array_merge(array("" => t("« none »")), $locales); - $selected_locale = ($user && $user->locale) ? $user->locale : ""; - $form->dropdown("locale") - ->label(t("Language Preference")) - ->options($locales) - ->selected($selected_locale); - } - } - - static function get_delete_form_admin($user) { - $form = new Forge("admin/users/delete_user/$user->id", "", "post", - array("id" => "gDeleteUserForm")); - $group = $form->group("delete_user")->label( - t("Are you sure you want to delete user %name?", array("name" => $user->name))); - $group->submit("")->value(t("Delete user %name", array("name" => $user->name))); - return $form; - } - - static function get_login_form($url) { - $form = new Forge($url, "", "post", array("id" => "gLoginForm")); - $group = $form->group("login")->label(t("Login")); - $group->input("name")->label(t("Username"))->id("gUsername")->class(null); - $group->password("password")->label(t("Password"))->id("gPassword")->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. * @@ -183,18 +36,6 @@ class user_Core { } /** - * 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 @@ -267,91 +108,69 @@ class user_Core { } /** - * 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) { - $user = model_cache::get("user", $id); - if ($user->loaded) { - return $user; - } - return null; + return self::_lookup_user_by_field("id", $id); } /** * Look up a user by name. - * @param integer $id the user 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) { - $user = model_cache::get("user", $name, "name"); - if ($user->loaded) { - return $user; - } - return null; + return self::_lookup_user_by_field("name", $name); } /** - * Create a hashed password using md5 plus salt. - * @param string $password plaintext password - * @param string $salt (optional) salt or hash containing salt (randomly generated if omitted) - * @return string hashed password + * 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. */ - private static function _md5Salt($password, $salt="") { - if (empty($salt)) { - for ($i = 0; $i < 4; $i++) { - $char = mt_rand(48, 109); - $char += ($char > 90) ? 13 : ($char > 57) ? 7 : 0; - $salt .= chr($char); + 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); } - } else { - $salt = substr($salt, 0, 4); } - return $salt . md5($salt . $password); + return $user->find_all(); } - static function cookie_locale() { - $cookie_data = Input::instance()->cookie("g_locale"); - $locale = null; - if ($cookie_data) { - if (preg_match("/^([a-z]{2,3}(?:_[A-Z]{2})?)$/", trim($cookie_data), $matches)) { - $requested_locale = $matches[1]; - $installed_locales = locales::installed(); - if (isset($installed_locales[$requested_locale])) { - $locale = $requested_locale; - } + /** + * 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 $locale; + 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 ede4e515..cf91812e 100644 --- a/modules/user/helpers/user_event.php +++ b/modules/user/helpers/user_event.php @@ -17,37 +17,14 @@ * 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_event_Core { - /** - * Initialization. - */ - static function gallery_ready() { - user::load_user(); - self::set_request_locale(); - } +class user_event_Core { static function admin_menu($menu, $theme) { - $menu->add_after("appearance_menu", - Menu::factory("link") + $menu->add_after("appearance_menu", Menu::factory("link") ->id("users_groups") ->label(t("Users/Groups")) ->url(url::site("admin/users"))); - } - static function set_request_locale() { - // 1. Check the session specific preference (cookie) - $locale = user::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); - } + return $menu; } } diff --git a/modules/user/helpers/user_installer.php b/modules/user/helpers/user_installer.php index 8ef4f13d..0cba502f 100644 --- a/modules/user/helpers/user_installer.php +++ b/modules/user/helpers/user_installer.php @@ -70,9 +70,18 @@ class user_installer { $admin->admin = true; $admin->save(); - // Let the admin own everything - $db->update("items", array("owner_id" => $admin->id), array("owner_id" => "IS NULL")); - module::set_version("user", 1); + $current_provider = module::get_var("gallery", "identity_provider"); + if (empty($current_provider)) { + // If there is no provider defined then we are doing an initial install + // so we need to set the provider and make the administrator own everything + // If the installer is called and there is an identity provider, then we + // are switching identity providers and and the event handlers will do the + // right things + module::set_var("gallery", "identity_provider", "user"); + + // Let the admin own everything + $db->query("update {items} set owner_id = {$admin->id}"); + } $root = ORM::factory("item", 1); access::allow($everybody, "view", $root); @@ -80,6 +89,18 @@ class user_installer { access::allow($registered, "view", $root); access::allow($registered, "view_full", $root); + + module::set_var("user", "mininum_password_length", 5); + + module::set_version("user", 2); + } + + static function upgrade($version) { + if ($version == 1) { + module::set_var("user", "mininum_password_length", 5); + + module::set_version("user", $version = 2); + } } static function uninstall() { @@ -92,11 +113,6 @@ class user_installer { $group->delete(); } - 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};"); diff --git a/modules/user/helpers/user_theme.php b/modules/user/helpers/user_theme.php index 098d87fd..31e2e8c0 100644 --- a/modules/user/helpers/user_theme.php +++ b/modules/user/helpers/user_theme.php @@ -19,35 +19,12 @@ */ class user_theme_Core { static function head($theme) { - if (count(locales::installed())) { - // Needed by the languages block - $theme->script("jquery.cookie.js"); - } - return ""; + $theme->css("user.css"); + $theme->script("password_strength.js"); } - static function header_top($theme) { - if ($theme->page_type != "login") { - $view = new View("login.html"); - $view->user = user::active(); - return $view->render(); - } + static function admin_head($theme) { + $theme->css("user.css"); + $theme->script("password_strength.js"); } - - static function sidebar_blocks($theme) { - $locales = locales::installed(); - foreach ($locales as $locale => $display_name) { - $locales[$locale] = SafeString::of_safe_html($display_name); - } - if (count($locales) > 1) { - $block = new Block(); - $block->css_id = "gUserLanguageBlock"; - $block->title = t("Language Preference"); - $block->content = new View("user_languages_block.html"); - $block->content->installed_locales = - array_merge(array("" => t("« none »")), $locales); - $block->content->selected = (string) user::cookie_locale(); - return $block; - } - } -} +}
\ No newline at end of file diff --git a/modules/user/images/progressImg1.png b/modules/user/images/progressImg1.png Binary files differnew file mode 100644 index 00000000..a9093647 --- /dev/null +++ b/modules/user/images/progressImg1.png diff --git a/modules/user/js/password_strength.js b/modules/user/js/password_strength.js new file mode 100644 index 00000000..2442b8de --- /dev/null +++ b/modules/user/js/password_strength.js @@ -0,0 +1,39 @@ +(function($) { + // Based on the Password Strength Indictor By Benjamin Sterling + // http://benjaminsterling.com/password-strength-indicator-and-generator/ + $.widget("ui.user_password_strength", { + _init: function() { + var self = this; + $(this.element).keyup(function() { + var strength = self.calculateStrength (this.value); + var index = Math.min(Math.floor( strength / 10 ), 10); + $("#g-password-gauge") + .removeAttr('class') + .addClass( "g-password-strength0" ) + .addClass( self.options.classes[ index ] ); + }).after("<div id='g-password-gauge' class='g-password-strength0'></div>"); + }, + + calculateStrength: function(value) { + // Factor in the length of the password + var strength = Math.min(5, value.length) * 10 - 20; + // Factor in the number of numbers + strength += Math.min(3, value.length - value.replace(/[0-9]/g,"").length) * 10; + // Factor in the number of non word characters + strength += Math.min(3, value.length - value.replace(/\W/g,"").length) * 15; + // Factor in the number of Upper case letters + strength += Math.min(3, value.length - value.replace(/[A-Z]/g,"").length) * 10; + + // Normalizxe between 0 and 100 + return Math.max(0, Math.min(100, strength)); + } + }); + $.extend($.ui.user_password_strength, { + defaults: { + classes : ['g-password-strength10', 'g-password-strength20', 'g-password-strength30', + 'g-password-strength40', 'g-password-strength50', 'g-password-strength60', + 'g-password-strength70',' g-password-strength80',' g-password-strength90', + 'g-password-strength100'] + } + }); + })(jQuery); diff --git a/modules/user/libraries/drivers/IdentityProvider/Gallery.php b/modules/user/libraries/drivers/IdentityProvider/Gallery.php new file mode 100644 index 00000000..f02c53a2 --- /dev/null +++ b/modules/user/libraries/drivers/IdentityProvider/Gallery.php @@ -0,0 +1,161 @@ +<?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 IdentityProvider_Gallery_Driver implements IdentityProvider_Driver { + /** + * @see IdentityProvider_Driver::guest. + */ + public function guest() { + return user::guest(); + } + + /** + * @see IdentityProvider_Driver::guest. + */ + public function admin_user() { + return self::lookup_user(2); + } + + /** + * @see IdentityProvider_Driver::create_user. + */ + public function create_user($name, $full_name, $password) { + return user::create($name, $full_name, $password); + } + + /** + * @see IdentityProvider_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 IdentityProvider_Driver::lookup_user. + */ + public function lookup_user($id) { + return user::lookup($id); + } + + /** + * @see IdentityProvider_Driver::lookup_user_by_name. + */ + public function lookup_user_by_name($name) { + return user::lookup_by_name($name); + } + + /** + * @see IdentityProvider_Driver::create_group. + */ + public function create_group($name) { + return group::create($name); + } + + /** + * @see IdentityProvider_Driver::everybody. + */ + public function everybody() { + return group::everybody(); + } + + /** + * @see IdentityProvider_Driver::registered_users. + */ + public function registered_users() { + return group::registered_users(); + } + + /** + * @see IdentityProvider_Driver::lookup_group. + */ + public function lookup_group($id) { + return group::lookup($id); + } + + /** + * @see IdentityProvider_Driver::lookup_group_by_name. + */ + public function lookup_group_by_name($name) { + return group::lookup_by_name($name); + } + + /** + * @see IdentityProvider_Driver::get_user_list. + */ + public function get_user_list($ids) { + return ORM::factory("user") + ->in("id", $ids) + ->find_all() + ->as_array(); + } + + /** + * @see IdentityProvider_Driver::groups. + */ + public function groups() { + return ORM::factory("group")->find_all(); + } + + /** + * @see IdentityProvider_Driver::add_user_to_group. + */ + static function add_user_to_group($user, $group_id) { + $group = self::lookup_group($group_id); + + $group->add($user); + $group->save(); + } + + /** + * @see IdentityProvider_Driver::remove_user_to_group. + */ + static function remove_user_from_group($user, $group_id) { + $group = self::lookup_group_by_name($group_id); + $group->remove($user); + $group->save(); + } +} // 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..184ce70a 100644 --- a/modules/user/models/user.php +++ b/modules/user/models/user.php @@ -17,11 +17,11 @@ * 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( - "name" => "length[1,32]", + "name" => "required|length[1,32]", "full_name" => "length[0,255]", "email" => "valid_email|length[1,255]", "password" => "length[1,40]", @@ -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/module.info b/modules/user/module.info index 8a9af407..7178f108 100644 --- a/modules/user/module.info +++ b/modules/user/module.info @@ -1,3 +1,6 @@ name = "Users and Groups" -description = "Provides user and group management" -version = 1 +description = "Gallery 3 user and group management" +version = 2 + +; Don't show this module on the module administration screen +no_module_admin = 1 diff --git a/modules/user/tests/No_Direct_ORM_Access_Test.php b/modules/user/tests/No_Direct_ORM_Access_Test.php new file mode 100644 index 00000000..440321fa --- /dev/null +++ b/modules/user/tests/No_Direct_ORM_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(MODPATH . "gallery/tests/Gallery_Filters.php"); + +class No_Direct_ORM_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/user/views/admin_users.html.php b/modules/user/views/admin_users.html.php index c065e4b1..45d04916 100644 --- a/modules/user/views/admin_users.html.php +++ b/modules/user/views/admin_users.html.php @@ -2,15 +2,15 @@ <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(){ - $("#gUserAdminList .core-info").draggable({ + $("#g-user-admin-list .g-core-info").draggable({ helper: "clone" }); - $("#gGroupAdmin .gGroup").droppable({ - accept: ".core-info", - hoverClass: "gSelected", + $("#g-group-admin .g-group").droppable({ + accept: ".g-core-info", + hoverClass: "g-selected", drop: function(ev, ui) { - var user_id = $(ui.draggable).attr("id").replace("user-", ""); - var group_id = $(this).attr("id").replace("group-", ""); + var user_id = $(ui.draggable).attr("id").replace("g-user-", ""); + var group_id = $(this).attr("id").replace("g-group-", ""); $.get(add_user_to_group_url.replace("__USERID__", user_id).replace("__GROUPID__", group_id), {}, function() { @@ -18,8 +18,8 @@ }); } }); - $("#group-1").droppable("destroy"); - $("#group-2").droppable("destroy"); + $("#g-group-1").droppable("destroy"); + $("#g-group-2").droppable("destroy"); }); var reload_group = function(group_id) { @@ -27,8 +27,8 @@ $.get(reload_group_url.replace("__GROUPID__", group_id), {}, function(data) { - $("#group-" + group_id).html(data); - $("#group-" + group_id + " .gDialogLink").gallery_dialog(); + $("#g-group-" + group_id).html(data); + $("#g-group-" + group_id + " .g-dialog-link").gallery_dialog(); }); } @@ -41,88 +41,93 @@ }); } </script> -<div class="gBlock"> - <a href="<?= url::site("admin/users/add_user_form") ?>" - class="gDialogLink gButtonLink right ui-icon-left ui-state-default ui-corner-all" - title="<?= t("Create a new user")->for_html_attr() ?>"> - <span class="ui-icon ui-icon-circle-plus"></span> - <?= t("Add a new user") ?> - </a> - <h2> - <?= t("User Admin") ?> - </h2> +<div class="g-block"> + <h1> <?= t("Users and groups") ?> </h1> - <div class="gBlockContent"> - <table id="gUserAdminList"> - <tr> - <th><?= t("Username") ?></th> - <th><?= t("Full name") ?></th> - <th><?= t("Email") ?></th> - <th><?= t("Last login") ?></th> - <th><?= t("Actions") ?></th> - </tr> + <div class="g-block-content"> - <? foreach ($users as $i => $user): ?> - <tr id="gUser-<?= $user->id ?>" class="<?= text::alternate("gOddRow", "gEvenRow") ?> user <?= $user->admin ? "admin" : "" ?>"> - <td id="user-<?= $user->id ?>" class="core-info gDraggable"> - <img src="<?= $user->avatar_url(20, $theme->url("images/avatar.jpg", true)) ?>" - title="<?= t("Drag user onto group below to add as a new member")->for_html_attr() ?>" - alt="<?= html::clean_attribute($user->name) ?>" - width="20" - height="20" /> - <?= html::clean($user->name) ?> - </td> - <td> - <?= html::clean($user->full_name) ?> - </td> - <td> - <?= html::clean($user->email) ?> - </td> - <td> - <?= ($user->last_login == 0) ? "" : gallery::date($user->last_login) ?> - </td> - <td class="gActions"> - <a href="<?= url::site("admin/users/edit_user_form/$user->id") ?>" - open_text="<?= t("close") ?>" - class="gPanelLink gButtonLink ui-state-default ui-corner-all ui-icon-left"> - <span class="ui-icon ui-icon-pencil"></span><span class="gButtonText"><?= t("edit") ?></span></a> - <? if (user::active()->id != $user->id && !$user->guest): ?> - <a href="<?= url::site("admin/users/delete_user_form/$user->id") ?>" - class="gDialogLink gButtonLink ui-state-default ui-corner-all ui-icon-left"> - <span class="ui-icon ui-icon-trash"></span><?= t("delete") ?></a> - <? else: ?> - <span title="<?= t("This user cannot be deleted")->for_html_attr() ?>" - class="gButtonLink ui-state-disabled ui-corner-all ui-icon-left"> - <span class="ui-icon ui-icon-trash"></span><?= t("delete") ?></span> - <? endif ?> - </td> - </tr> - <? endforeach ?> - </table> - </div> -</div> + <div id="g-user-admin" class="g-block"> + <a href="<?= url::site("admin/users/add_user_form") ?>" + class="g-dialog-link g-button g-right ui-icon-left ui-state-default ui-corner-all" + title="<?= t("Create a new user")->for_html_attr() ?>"> + <span class="ui-icon ui-icon-circle-plus"></span> + <?= t("Add a new user") ?> + </a> + + <h2> <?= t("Users") ?> </h2> + + <div class="g-block-content"> + <table id="g-user-admin-list"> + <tr> + <th><?= t("Username") ?></th> + <th><?= t("Full name") ?></th> + <th><?= t("Email") ?></th> + <th><?= t("Last login") ?></th> + <th><?= t("Actions") ?></th> + </tr> + + <? foreach ($users as $i => $user): ?> + <tr id="g-user-<?= $user->id ?>" class="<?= text::alternate("g-odd", "g-even") ?> g-user <?= $user->admin ? "g-admin" : "" ?>"> + <td id="g-user-<?= $user->id ?>" class="g-core-info g-draggable"> + <img src="<?= $user->avatar_url(20, $theme->url("images/avatar.jpg", true)) ?>" + title="<?= t("Drag user onto a group to add as a new member")->for_html_attr() ?>" + alt="<?= html::clean_attribute($user->name) ?>" + width="20" + height="20" /> + <?= html::clean($user->name) ?> + </td> + <td> + <?= html::clean($user->full_name) ?> + </td> + <td> + <?= html::clean($user->email) ?> + </td> + <td> + <?= ($user->last_login == 0) ? "" : gallery::date($user->last_login) ?> + </td> + <td> + <a href="<?= url::site("admin/users/edit_user_form/$user->id") ?>" + 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 (identity::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> + <? else: ?> + <span title="<?= t("This user cannot be deleted")->for_html_attr() ?>" + class="g-button ui-state-disabled ui-corner-all ui-icon-left"> + <span class="ui-icon ui-icon-trash"></span><?= t("Delete") ?></span> + <? endif ?> + </td> + </tr> + <? endforeach ?> + </table> + </div> + </div> + + <div id="g-group-admin" class="g-block g-right ui-helper-clearfix"> + <a href="<?= url::site("admin/users/add_group_form") ?>" + class="g-dialog-link g-button g-right ui-icon-left ui-state-default ui-corner-all" + title="<?= t("Create a new group")->for_html_attr() ?>"> + <span class="ui-icon ui-icon-circle-plus"></span> + <?= t("Add a new group") ?> + </a> -<div id="gGroupAdmin" class="gBlock"> - <a href="<?= url::site("admin/users/add_group_form") ?>" - class="gDialogLink gButtonLink right ui-icon-left ui-state-default ui-corner-all" - title="<?= t("Create a new group")->for_html_attr() ?>"> - <span class="ui-icon ui-icon-circle-plus"></span> - <?= t("Add a new group") ?> - </a> + <h2> <?= t("Groups") ?> </h2> - <h2> - <?= t("Group Admin") ?> - </h2> + <div class="g-block-content"> + <ul> + <? foreach ($groups as $i => $group): ?> + <li id="g-group-<?= $group->id ?>" class="g-group g-left <?= ($group->special ? "g-default-group" : "") ?>" /> + <? $v = new View("admin_users_group.html"); $v->group = $group; ?> + <?= $v ?> + </li> + <? endforeach ?> + </ul> + </div> + </div> - <div class="gBlockContent"> - <ul> - <? foreach ($groups as $i => $group): ?> - <li id="group-<?= $group->id ?>" class="gGroup <?= ($group->special ? "gDefaultGroup" : "") ?>" /> - <? $v = new View("admin_users_group.html"); $v->group = $group; ?> - <?= $v ?> - </li> - <? endforeach ?> - </ul> </div> </div> diff --git a/modules/user/views/admin_users_group.html.php b/modules/user/views/admin_users_group.html.php index 476e0817..b7e573b3 100644 --- a/modules/user/views/admin_users_group.html.php +++ b/modules/user/views/admin_users_group.html.php @@ -4,26 +4,26 @@ <? if (!$group->special): ?> <a href="<?= url::site("admin/users/delete_group_form/$group->id") ?>" title="<?= t("Delete the %name group", array("name" => $group->name))->for_html_attr() ?>" - class="gDialogLink gButtonLink ui-state-default ui-corner-all"> - <span class="ui-icon ui-icon-trash"><?= t("delete") ?></span></a> + class="g-dialog-link g-button g-right"> + <span class="ui-icon ui-icon-trash"><?= t("Delete") ?></span></a> <? else: ?> <a title="<?= t("This default group cannot be deleted")->for_html_attr() ?>" - class="gDialogLink gButtonLink ui-state-disabled ui-corner-all ui-icon-left"> - <span class="ui-icon ui-icon-trash"><?= t("delete") ?></span></a> + class="g-button g-right ui-state-disabled ui-icon-left"> + <span class="ui-icon ui-icon-trash"><?= t("Delete") ?></span></a> <? endif ?> </h4> <? if ($group->users->count() > 0): ?> -<ul> +<ul class="g-member-list"> <? foreach ($group->users as $i => $user): ?> - <li class="gUser"> + <li class="g-user"> <?= html::clean($user->name) ?> <? if (!$group->special): ?> <a href="javascript:remove_user(<?= $user->id ?>, <?= $group->id ?>)" - class="gButtonLink ui-state-default ui-corner-all ui-icon-left" + class="g-button g-right ui-state-default ui-corner-all ui-icon-left" title="<?= t("Remove %user from %group group", array("user" => $user->name, "group" => $group->name))->for_html_attr() ?>"> - <span class="ui-icon ui-icon-closethick"><?= t("remove") ?></span> + <span class="ui-icon ui-icon-closethick"><?= t("Remove") ?></span> </a> <? endif ?> </li> @@ -31,8 +31,8 @@ </ul> <? else: ?> <div> - <p> - <?= t("Drag & drop users from the User Admin above into this group box to add group members.") ?> + <p class="ui-state-disabled"> + <?= t("Drag & drop users from the \"Users\" list onto this group to add group members.") ?> </p> </div> <? endif ?> diff --git a/modules/user/views/login.html.php b/modules/user/views/login.html.php deleted file mode 100644 index bb670d51..00000000 --- a/modules/user/views/login.html.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<ul id="gLoginMenu"> - <? if ($user->guest): ?> - <li class="first"> - <a href="<?= url::site("login/ajax") ?>" - title="<?= t("Login to Gallery")->for_html_attr() ?>" - id="gLoginLink"><?= t("Login") ?></a> - </li> - <? else: ?> - <li class="first"> - <?= 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="gUserProfileLink" class="gDialogLink">' . - html::clean($user->display_name()) . '</a>'))) ?> - </li> - <li> - <a href="<?= url::site("logout?csrf=$csrf&continue=" . urlencode(url::current(true))) ?>" - id="gLogoutLink"><?= t("Logout") ?></a> - </li> - <? endif ?> -</ul> diff --git a/modules/user/views/login_ajax.html.php b/modules/user/views/login_ajax.html.php deleted file mode 100644 index 56bc1cbd..00000000 --- a/modules/user/views/login_ajax.html.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<script type="text/javascript"> - $("#gLoginForm").ready(function() { - $("#gForgotPasswordLink").click(function() { - $.ajax({ - url: "<?= url::site("password/reset") ?>", - success: function(data) { - $("div#gLoginView").html(data); - $("#ui-dialog-title-gDialog").html(<?= t("Reset Password")->for_js() ?>); - ajaxify_login_reset_form(); - } - }); - }); - }); - - function ajaxify_login_reset_form() { - $("#gLoginView form").ajaxForm({ - dataType: "json", - success: function(data) { - if (data.form) { - $("#gLoginView form").replaceWith(data.form); - ajaxify_login_reset_form(); - } - if (data.result == "success") { - $("#gDialog").dialog("close"); - window.location.reload(); - } - - } - }); - }; -</script> -<div id="gLoginView"> - <ul> - <li> - <div id="gLoginViewForm"> - <?= $form ?> - </div> - </li> - <li> - <a href="#" id="gForgotPasswordLink"><?= t("Forgot Your Password?") ?></a> - </li> - </ul> -</div> diff --git a/modules/user/views/reset_password.html.php b/modules/user/views/reset_password.html.php index 92ca4917..3afca881 100644 --- a/modules/user/views/reset_password.html.php +++ b/modules/user/views/reset_password.html.php @@ -1,10 +1,10 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> <html> <head> - <title><?= t("Password Reset Request") ?> </title> + <title><?= t("Password reset request") ?> </title> </head> <body> - <h2><?= t("Password Reset Request") ?> </h2> + <h2><?= t("Password reset request") ?> </h2> <p> <?= t("Hello, %name,", array("name" => $user->full_name ? $user->full_name : $user->name)) ?> </p> diff --git a/modules/user/views/user_form.html.php b/modules/user/views/user_form.html.php new file mode 100644 index 00000000..039ae8a5 --- /dev/null +++ b/modules/user/views/user_form.html.php @@ -0,0 +1,7 @@ +<?php defined("SYSPATH") or die("No direct script access.") ?> +<script type="text/javascript"> + $("form").ready(function(){ + $('input[name="password"]').user_password_strength(); + }); +</script> +<?= $form ?> diff --git a/modules/user/views/user_languages_block.html.php b/modules/user/views/user_languages_block.html.php deleted file mode 100644 index b5ae674c..00000000 --- a/modules/user/views/user_languages_block.html.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php defined("SYSPATH") or die("No direct script access.") ?> -<?= form::dropdown("gSelectSessionLocale", $installed_locales, $selected) ?> -<script type="text/javascript"> - $("#gSelectSessionLocale").change(function() { - var old_locale_preference = <?= html::js_string($selected) ?>; - var locale = $(this).val(); - if (old_locale_preference == locale) { - return; - } - - var expires = -1; - if (locale) { - expires = 365; - } - $.cookie("g_locale", locale, {"expires": expires, "path": "/"}); - window.location.reload(true); - }); -</script> - |