Skip to content

Commit

Permalink
Merge branch 'kohana_3' of github.com:gallery/gallery3 into kohana_3
Browse files Browse the repository at this point in the history
  • Loading branch information
bharat committed Apr 30, 2013
2 parents 4b39989 + 4374541 commit e7f67cf
Show file tree
Hide file tree
Showing 15 changed files with 231 additions and 141 deletions.
2 changes: 1 addition & 1 deletion modules/formo/classes/Formo/Core/Innards.php
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ protected function _run_callbacks($type = NULL)
$callbacks = Arr::get($this->_callbacks, $key, array());
foreach ($callbacks as $callback)
{
$result = $callback($this);
$result = call_user_func($callback, $this);

if ($value === TRUE AND $result === FALSE)
{
Expand Down
18 changes: 10 additions & 8 deletions modules/gallery/classes/Gallery/Auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ static function login($user) {
Module::event("user_login", $user);
}

static function reauthenticate($user) {
if (!Request::current()->is_ajax()) {
Message::success(t("Successfully re-authenticated!"));
}
Module::event("user_auth", $user);
}

static function logout() {
$user = Identity::active_user();
if (!$user->guest) {
Expand Down Expand Up @@ -68,15 +75,10 @@ static function too_many_failures($name) {

/**
* Validate that there haven't been too many failed login attempts.
* This uses a syntax similar to Valid::matches().
*/
static function validate_too_many_failed_logins($name) {
return !Auth::too_many_failures($name);
}

static function validate_too_many_failed_auth_attempts($form_input) {
if (Auth::too_many_failures(Identity::active_user()->name)) {
$form_input->add_error("too_many_failed_auth_attempts", 1);
}
static function validate_too_many_failed_logins($array, $name) {
return !Auth::too_many_failures($array[$name]);
}

/**
Expand Down
4 changes: 0 additions & 4 deletions modules/gallery/classes/Gallery/Controller/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ public function check_auth($auth) {
}
}

if ($this->request->method() == HTTP_Request::POST) {
Access::verify_csrf();
}

return parent::check_auth($auth);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,41 @@ public function action_index() {
public function action_edit() {
$module_name = $this->request->arg(0, "alpha_dash");
$var_name = $this->request->arg(1);
$value = Module::get_var($module_name, $var_name);

if (Module::is_installed($module_name)) {
$value = Module::get_var($module_name, $var_name);
$form = new Forge("admin/advanced_settings/save/$module_name/$var_name", "", "post");
$group = $form->group("edit_var")->label(t("Edit setting"));
$group->input("module_name")->label(t("Module"))->value($module_name)->disabled(1);
$group->input("var_name")->label(t("Setting"))->value($var_name)->disabled(1);
$group->textarea("value")->label(t("Value"))->value($value);
$group->submit("")->value(t("Save"));
$this->response->body($form);
if (!Module::is_installed($module_name)) {
throw HTTP_Exception::factory(400);
}
}

public function action_save() {
$module_name = $this->request->arg(0, "alpha_dash");
$var_name = $this->request->arg(1);
Access::verify_csrf();
$form = Formo::form()
->add("edit_var", "group");
$form->edit_var
->add("module_name", "input", $module_name)
->add("var_name", "input", $var_name)
->add("value", "textarea", $value)
->add("submit", "input|submit", t("Save"));

if (Module::is_installed($module_name)) {
Module::set_var($module_name, $var_name, $this->request->post("value"));
$form->edit_var
->set("label", t("Edit setting"));
$form->edit_var->module_name
->attr("disabled", "disabled")
->set("label", t("Module"));
$form->edit_var->var_name
->attr("disabled", "disabled")
->set("label", t("Setting"));
$form->edit_var->value
->set("label", t("Value"));

if ($form->load()->validate()) {
Module::set_var($module_name, $var_name, $form->edit_var->value->val());
Message::success(
t("Saved value for %var (%module_name)",
array("var" => $var_name, "module_name" => $module_name)));

$this->response->json(array("result" => "success"));
return;
}

$this->response->body($form);
}
}
4 changes: 2 additions & 2 deletions modules/gallery/classes/Gallery/Controller/FileProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ public function action_index() {
} else {
// Send the file as the response. The filename will be set automatically from the path.
// Note: send_file() will automatically halt script execution after sending the file.
$this->response->send_file($file, null,
array("inline" => "true", "mime_type" => $mime_type));
$options = array("inline" => "true", "mime_type" => $mime_type);
$this->response->send_file($file, null, $options);
}
}
}
5 changes: 4 additions & 1 deletion modules/gallery/classes/Gallery/Controller/Login.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ class Gallery_Controller_Login extends Controller {
public $allow_private_gallery = true;

public function action_index() {
// By design, this bears a strong resemblance to the reauthenticate controller.
// For details on the differences, see the notes in the reauthenticate controller.

// Define our login form.
$form = Formo::form()
->add("continue_url", "input|hidden", Session::instance()->get("continue_url"))
Expand All @@ -39,7 +42,7 @@ public function action_index() {
$form->login->username
->attr("id", "g-username")
->set("label", t("Username"))
->add_rule("Auth::validate_too_many_failed_logins", array(":value"),
->add_rule("Auth::validate_too_many_failed_logins", array(":form_val", "username"),
t("Too many failed login attempts. Try again later"))
->add_rule("Auth::validate_username_and_password", array(":form_val", "username", "password"),
t("Invalid name or password"));
Expand Down
155 changes: 86 additions & 69 deletions modules/gallery/classes/Gallery/Controller/Reauthenticate.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,87 +19,104 @@
*/
class Gallery_Controller_Reauthenticate extends Controller {
public function action_index() {
$is_ajax = Session::instance()->get_once("is_ajax_request", $this->request->is_ajax());
if (!Identity::active_user()->admin) {
if ($is_ajax) {
// We should never be able to get here since Controller_Admin::_reauth_check() won't work
// for non-admins.
// By design, this bears a strong resemblance to the login controller. Aside from a
// search'n'replace for login and reauthenticate, the differences are that:
// - it's restricted to admins
// - it's fixed to the current user
// - it doesn't need allow_maintenance_mode or allow_private_gallery, which would be
// redundant with the admin-only restriction
// - the username field is hidden with a pre-filled value, and has rules that enforce it's the
// current user
// - the main validation rules have moved from username to password so errors are shown there
// - the field labels are different
// - the username is added to the view
// - some ajax replies are different (@todo: try and unify this)

$user = Identity::active_user();

if (!$user->admin) {
if ($this->request->is_ajax()) {
// We should never be able to get here since the admin reauth_check
// won't work for non-admins.
Access::forbidden();
} else {
// The user could have navigated here directly. This isn't a security
// breach, but they still shouldn't be here.
$this->redirect(Item::root()->abs_url());
}
}

// On redirects from the admin controller, the ajax request indicator is lost,
// so we store it in the session.
if ($is_ajax) {
$v = new View("gallery/reauthenticate.html");
$v->form = self::_form();
$v->user_name = Identity::active_user()->name;
$this->response->body($v);
} else {
self::_show_form(self::_form());
}
}
// Define our reauthenticate form.
$form = Formo::form()
->add("continue_url", "input|hidden", Session::instance()->get("continue_url"))
->add("reauthenticate", "group");
$form->reauthenticate
->add("username", "input|hidden", Identity::active_user()->name)
->add("password", "input|password")
->add("submit", "input|submit", t("Submit"));

public function action_auth() {
if (!Identity::active_user()->admin) {
Access::forbidden();
}
Access::verify_csrf();
$form
->attr("id", "g-reauthenticate-form")
->attr("class", "g-narrow");
$form->reauthenticate
->set("label", t("Re-authenticate"));
$form->reauthenticate->username
->set("can_be_empty", true)
->add_rule("equals", array(":value", $user->name))
->callback("fail", array("Access::forbidden"));
$form->reauthenticate->password
->attr("id", "g-password")
->set("label", t("Password"))
->add_rule("Auth::validate_too_many_failed_logins", array(":form_val", "username"),
t("Too many incorrect passwords. Try again later"))
->add_rule("Auth::validate_username_and_password", array(":form_val", "username", "password"),
t("Incorrect password"));

$form = self::_form();
$valid = $form->validate();
$user = Identity::active_user();
if ($valid) {
Module::event("user_auth", $user);
if (!$this->request->is_ajax()) {
Message::success(t("Successfully re-authenticated!"));
}
$this->redirect(Session::instance()->get_once("continue_url"));
} else {
$name = $user->name;
GalleryLog::warning("user", t("Failed re-authentication for %name", array("name" => $name)));
Module::event("user_auth_failed", $name);
if ($this->request->is_ajax()) {
$v = new View("gallery/reauthenticate.html");
$v->form = $form;
$v->user_name = Identity::active_user()->name;
$this->response->json(array("html" => (string)$v));
} else {
self::_show_form($form);
}
}
}
// Define our basic form view.
$view = new View("gallery/reauthenticate.html");
$view->form = $form;
$view->username = $form->reauthenticate->username->val();

protected static function _show_form($form) {
$view = new View_Theme("required/page.html", "other", "reauthenticate");
$view->page_title = t("Re-authenticate");
$view->content = new View("gallery/reauthenticate.html");
$view->content->form = $form;
$view->content->user_name = Identity::active_user()->name;
if ($form->sent()) {
// Reauthenticate attempted - regenerate the session id to avoid session trapping.
Session::instance()->regenerate();

$this->response->body($view);
}
if ($form->load()->validate()) {
// Reauthenticate attempt is valid.
Auth::reauthenticate($user);

protected static function _form() {
$form = new Forge("reauthenticate/auth", "", "post", array("id" => "g-reauthenticate-form"));
$form->set_attr("class", "g-narrow");
$group = $form->group("reauthenticate")->label(t("Re-authenticate"));
$group->password("password")->label(t("Password"))->id("g-password")->class(null)
->callback("Auth::validate_too_many_failed_auth_attempts")
->callback("Controller_Reauthenticate::valid_password")
->error_messages("invalid_password", t("Incorrect password"))
->error_messages(
"too_many_failed_auth_attempts",
t("Too many incorrect passwords. Try again later"));
$group->submit("")->value(t("Submit"));
return $form;
}
if ($this->request->is_ajax()) {
// @todo: make reauthenticate and login use the same type of response here
$continue_url = $form->continue_url->val();
$this->redirect($continue_url ? $continue_url : Item::root()->abs_url());
} else {
$continue_url = $form->continue_url->val();
$this->redirect($continue_url ? $continue_url : Item::root()->abs_url());
}
} else {
// Reauthenticate attempt is invalid.
$name = $form->reauthenticate->username->val();
GalleryLog::warning("user", t("Failed re-authentication for %name", array("name" => $name)));
Module::event("user_auth_failed", $name);

public static function valid_password($password_input) {
if (!Identity::is_correct_password(Identity::active_user(), $password_input->value)) {
$password_input->add_error("invalid_password", 1);
if ($this->request->is_ajax()) {
// @todo: make reauthenticate and login use the same type of response here
$this->response->json(array("html" => (string)$view));
return;
}
}
}

// Reauthenticate not yet attempted (ajax or non-ajax) or reauthenticate failed (non-ajax).
if ($this->request->is_ajax()) {
// Send the basic reauthenticate view.
$this->response->body($view);
} else {
// Wrap the basic reauthenticate view in a theme.
$view_theme = new View_Theme("required/page.html", "other", "reauthenticate");
$view_theme->page_title = t("Re-authenticate");
$view_theme->content = $view;
$this->response->body($view_theme);
}
}
}
15 changes: 11 additions & 4 deletions modules/gallery/classes/Gallery/Formo.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,23 @@ public function add_rule($rule, $params=null, $error_message=null) {
}

/**
* See if the field has at least one group/subform. This is used when we render our
* Sort the child fields by whether they're groups or hidden. This is used when we render our
* custom templates.
*/
public function has_group() {
public function sort_children() {
$groups = array();
$non_groups = array();
$hidden = array();
foreach ($this->_fields as $field) {
if ($field->get("driver") == "group") {
return true;
$groups[] = $field;
} else if ($field->is_hidden()) {
$hidden[] = $field;
} else {
$non_groups[] = $field;
}
}
return false;
return array($groups, $non_groups, $hidden);
}

/**
Expand Down
12 changes: 4 additions & 8 deletions modules/gallery/classes/Gallery/Hook/Rest/Data.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,13 @@ static function get($request) {
if (TEST_MODE) {
return $file;
} else {
// Send the file as the response. The filename will be set automatically from the path.
// Note: send_file() will automatically halt script execution after sending the file.
$options = array("inline" => "true", "mime_type" => $mime_type);
if (isset($p->encoding) && $p->encoding == "base64") {
// Send the base64-encoded content as the response. This sets the filename as its basename.
$this->response->body(base64_encode(file_get_contents($file)));
$this->response->send_file(true, pathinfo($file, PATHINFO_BASENAME),
array("inline" => "true", "mime_type" => $mime_type));
} else {
// Send the file as the response. The filename will be set automatically from the path.
$this->response->send_file($file, null,
array("inline" => "true", "mime_type" => $mime_type));
$options["encoding"] = "base64";
}
$this->response->send_file($file, null, $options);
}
}

Expand Down
30 changes: 30 additions & 0 deletions modules/gallery/classes/Gallery/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,34 @@ public function json($message, $text_plain=false) {
}
$this->body(json_encode($message));
}

/**
* Overload Response::send_file() to handle the "encoding" option. Currently,
* the only value of encoding we act upon is "base64" which is used in REST.
* @see Response::send_file()
*/
public function send_file($filename, $download=null, array $options=null) {
if ($encoding = Arr::get($options, "encoding")) {
switch ($encoding) {
case "base64":
if ($filename === true) {
// Use the response body.
$this->response->body(base64_encode($this->response->body()));
} else {
// Load file into the response body, set download name if empty, reset the filename.
$this->response->body(base64_encode(file_get_contents($filename)));
if (empty($download)) {
$download = pathinfo($filename, PATHINFO_BASENAME);
}
$filename = true;
}
break;
default:
// Remove the encoding option to avoid confusion downstream.
unset($options["encoding"]);
}
}

return parent::send_file($filename, $download, $options);
}
}
Loading

0 comments on commit e7f67cf

Please sign in to comment.