public function anyEdit($id = null) { Auth::getUser()->hasPermissionOr401(Config::get("permissions.users"), 1); $user = null; $editing = false; if (!is_null($id)) { $user = User::with("permissionGroups")->find($id); if (is_null($user)) { App::abort(404); return; } $editing = true; } $formSubmitted = isset($_POST['form-submitted']) && $_POST['form-submitted'] === "1"; // has id 1 // populate $formData with default values or received values $formData = FormHelpers::getFormData(array(array("enabled", ObjectHelpers::getProp(false, $user, "disabled") ? "" : "y"), array("admin", ObjectHelpers::getProp(false, $user, "admin") ? "y" : ""), array("cosign-user", ObjectHelpers::getProp("", $user, "cosign_user")), array("user", ObjectHelpers::getProp("", $user, "username")), array("password", ""), array("password-changed", "0"), array("groups", json_encode(array()))), !$formSubmitted); $passwordToDisplay = null; if ($formData['password-changed'] === "1") { $passwordToDisplay = $formData['password']; } else { $passwordToDisplay = is_null(ObjectHelpers::getProp(null, $user, "password_hash")) ? "" : null; } $additionalFormData = array("passwordInitialData" => User::generateContentForPasswordToggleableComponent($passwordToDisplay), "passwordToggleEnabled" => !is_null(ObjectHelpers::getProp(null, $user, "password_hash")), "passwordChanged" => !is_null($passwordToDisplay), "groupsInitialData" => null); if (!$formSubmitted) { $additionalFormData['groupsInput'] = ObjectHelpers::getProp(json_encode(array()), $user, "groups_for_input"); $additionalFormData['groupsInitialData'] = ObjectHelpers::getProp(json_encode(array()), $user, "groups_for_orderable_list"); } else { $additionalFormData['groupsInput'] = PermissionGroup::generateInputValueForAjaxSelectOrderableList(JsonHelpers::jsonDecodeOrNull($formData['groups'], true)); $additionalFormData['groupsInitialData'] = PermissionGroup::generateInitialDataForAjaxSelectOrderableList(JsonHelpers::jsonDecodeOrNull($formData['groups'], true)); } $errors = null; if ($formSubmitted) { $modelCreated = DB::transaction(function () use(&$formData, &$user, &$errors) { Validator::extend('valid_password_changed_val', function ($attribute, $value, $parameters) { return $value === "0" || $value === "1"; }); Validator::extend('unique_user', function ($attribute, $value, $parameters) use(&$user) { $currentId = !is_null($user) ? intval($user->id) : null; $q = User::where("username", $value); if (!is_null($currentId)) { $q = $q->where("id", "!=", $currentId); } return $q->count() === 0; }); Validator::extend('unique_cosign_user', function ($attribute, $value, $parameters) use(&$user) { $currentId = !is_null($user) ? intval($user->id) : null; $q = User::where("cosign_user", $value); if (!is_null($currentId)) { $q = $q->where("id", "!=", $currentId); } return $q->count() === 0; }); Validator::extend('valid_groups', function ($attribute, $value, $parameters) { return PermissionGroup::isValidIdsFromAjaxSelectOrderableList(JsonHelpers::jsonDecodeOrNull($value, true)); }); $validator = Validator::make($formData, array('password-changed' => array('required', 'valid_password_changed_val'), 'cosign-user' => array('max:32', 'unique_cosign_user'), 'user' => array('required_with:password', 'alpha_dash', 'unique_user'), 'groups' => array('required', 'valid_groups')), array('password-changed.required' => "", 'password-changed.valid_password_changed_val' => "", 'cosign-user.max' => FormHelpers::getLessThanCharactersMsg(32), 'cosign-user.unique_cosign_user' => "There is already another account associated with this username.", 'user.required_with' => FormHelpers::getRequiredMsg(), 'user.required' => FormHelpers::getRequiredMsg(), 'user.unique_user' => "An account with this username already exists.", 'user.alpha_dash' => FormHelpers::getInvalidAlphaDashMsg(), 'password.required' => FormHelpers::getRequiredMsg(), 'groups.required' => FormHelpers::getGenericInvalidMsg(), 'groups.valid_groups' => FormHelpers::getGenericInvalidMsg())); // if user has not chosen to change password, but left user empty, this is not allowed. // user can only be empty when there is no password set. $validator->sometimes("user", "required", function ($input) use(&$formData) { return $formData['password-changed'] === "0"; }); $validator->sometimes("password", "required", function ($input) use(&$user, &$formData) { return !empty($formData['user']) && $formData['password-changed'] === "1"; }); if (!$validator->fails()) { // everything is good. save model // build the model now. Then validate that there is at least one admin. Done in this order so that resultsInNoAccessibleAdminLogin() works. if (is_null($user)) { $user = new User(); } $user->disabled = !FormHelpers::toBoolean($formData['enabled']); $user->admin = FormHelpers::toBoolean($formData['admin']); $user->cosign_user = FormHelpers::nullIfEmpty($formData['cosign-user']); $username = FormHelpers::nullIfEmpty($formData['user']); $user->username = $username; if (!is_null($username)) { if ($formData['password-changed'] === "1") { $password = FormHelpers::nullIfEmpty($formData['password']); $user->password_hash = !is_null($password) ? Hash::make($password) : null; } } else { $user->password_hash = null; } // validate that there is at least one admin with access. $validator = Validator::make($formData, array(), array('enabled.required' => "This user must be enabled otherwise there is no admin on the system with access.", 'admin.required' => "This user must be admin otherwise there is no admin on the system with access.", 'user.required' => "A user is required because there must be at least one admin in the system with a username and password.", 'password.required' => "A password is required because there must be at least one admin in the system with a username and password.")); $validator->sometimes(array("enabled", "admin", "user"), "required", function ($input) use(&$user) { return $user->resultsInNoAccessibleAdminLogin(); }); $validator->sometimes("password", "required", function ($input) use(&$user, &$formData) { return $user->resultsInNoAccessibleAdminLogin() && $formData['password-changed'] === "1"; }); if (!$validator->fails()) { if ($user->save() === false) { throw new Exception("Error saving User."); } $user->permissionGroups()->detach(); // detaches all $ids = json_decode($formData['groups'], true); if (count($ids) > 0) { $groups = PermissionGroup::whereIn("id", $ids)->get(); foreach ($groups as $a) { $user->permissionGroups()->attach($a); } } // the transaction callback result is returned out of the transaction function return true; } else { $errors = $validator->messages(); return false; } } else { $errors = $validator->messages(); return false; } }); if ($modelCreated) { return Redirect::to(Config::get("custom.admin_base_url") . "/users"); } // if not valid then return form again with errors } $view = View::make('home.admin.users.edit'); $view->editing = $editing; $view->form = $formData; $view->additionalForm = $additionalFormData; $view->formErrors = $errors; $view->cancelUri = Config::get("custom.admin_base_url") . "/users"; $this->setContent($view, "users", "users-edit"); }