/** * Returns a list of Users * * Generates a list of users, optionally paginated, sorted and/or filtered. * This page requires authentication. * Request type: GET */ public function listUsers() { $get = $this->_app->request->get(); $filters = isset($get['filters']) ? $get['filters'] : []; $primary_group_name = isset($get['primary_group']) ? $get['primary_group'] : null; // Optional filtering by primary group if ($primary_group_name) { $primary_group = Group::where('name', $primary_group_name)->first(); if (!$primary_group) { $this->_app->notFound(); } // Access-controlled page if (!$this->_app->user->checkAccess('uri_group_users', ['primary_group_id' => $primary_group->id])) { $this->_app->notFound(); } $userQuery = new User(); $userQuery = $userQuery->where('primary_group_id', $primary_group->id); } else { // Access-controlled page if (!$this->_app->user->checkAccess('uri_users')) { $this->_app->notFound(); } $userQuery = new User(); } // Count unpaginated total $total = $userQuery->count(); // Exclude fields $userQuery = $userQuery->exclude(['password', 'secret_token']); // Get unfiltered, unsorted, unpaginated collection $user_collection = $userQuery->get(); // Load recent events for all users and merge into the collection. This can't be done in one query, // at least not efficiently. See http://laravel.io/forum/04-05-2014-eloquent-eager-loading-to-limit-for-each-post $last_sign_in_times = $user_collection->getRecentEvents('sign_in'); $last_sign_up_times = $user_collection->getRecentEvents('sign_up', 'sign_up_time'); // Apply filters foreach ($filters as $name => $value) { // For date filters, search for weekday, month, or year if ($name == 'last_sign_in_time') { $user_collection = $user_collection->filterRecentEventTime('sign_in', $last_sign_in_times, $value); } else { if ($name == 'sign_up_time') { $user_collection = $user_collection->filterRecentEventTime('sign_up', $last_sign_up_times, $value, "Unknown"); } else { $user_collection = $user_collection->filterTextField($name, $value); } } } // Render $this->sortPaginateRender($user_collection, $total, 'users'); }
/** * Delete this group from the database, along with any linked user and authorization rules * */ public function delete() { // Remove all user associations $this->users()->detach(); // Remove all group auth rules $auth_table = Database::getSchemaTable('authorize_group')->name; Capsule::table($auth_table)->where("group_id", $this->id)->delete(); // Reassign any primary users to the current default primary group $default_primary_group = Group::where('is_default', GROUP_DEFAULT_PRIMARY)->first(); $user_table = Database::getSchemaTable('user')->name; Capsule::table($user_table)->where('primary_group_id', $this->id)->update(["primary_group_id" => $default_primary_group->id]); // TODO: assign user to the default primary group as well? // Delete the group $result = parent::delete(); return $result; }
/** * Returns a list of Users * * Generates a list of users, optionally paginated, sorted and/or filtered. * This page requires authentication. * Request type: GET * @param int $page optional. For paging, the page number to start with. * @param int $size optional. For paging, the number of results per page. * @param string $primary_group_name optional. If specified, will only display users in that particular primary group. */ public function listUsers($page = 0, $size = 10, $primary_group_name = null) { $get = $this->_app->request->get(); $size = isset($get['size']) ? $get['size'] : null; $page = isset($get['page']) ? $get['page'] : null; $sort_field = isset($get['sort_field']) ? $get['sort_field'] : "user_name"; $sort_order = isset($get['sort_order']) ? $get['sort_order'] : "asc"; $filters = isset($get['filters']) ? $get['filters'] : []; $format = isset($get['format']) ? $get['format'] : "json"; $primary_group_name = isset($get['primary_group']) ? $get['primary_group'] : null; // Optional filtering by primary group if ($primary_group_name) { $primary_group = Group::where('name', $primary_group_name)->first(); if (!$primary_group) { $this->_app->notFound(); } // Access-controlled page if (!$this->_app->user->checkAccess('uri_group_users', ['primary_group_id' => $primary_group->id])) { $this->_app->notFound(); } $userQuery = new User(); $userQuery = $userQuery->where('primary_group_id', $primary_group->id); } else { // Access-controlled page if (!$this->_app->user->checkAccess('uri_users')) { $this->_app->notFound(); } $userQuery = new User(); } // Count unpaginated total $total = $userQuery->count(); // Exclude fields $userQuery = $userQuery->exclude(['password', 'secret_token']); //Capsule::connection()->enableQueryLog(); // Get unfiltered, unsorted, unpaginated collection $user_collection = $userQuery->get(); // Load recent events for all users and merge into the collection. This can't be done in one query, // at least not efficiently. See http://laravel.io/forum/04-05-2014-eloquent-eager-loading-to-limit-for-each-post $last_sign_in_times = $user_collection->getRecentEvents('sign_in'); $last_sign_up_times = $user_collection->getRecentEvents('sign_up', 'sign_up_time'); // Apply filters foreach ($filters as $name => $value) { // For date filters, search for weekday, month, or year if ($name == 'last_sign_in_time') { $user_collection = $user_collection->filterRecentEventTime('sign_in', $last_sign_in_times, $value); } else { if ($name == 'sign_up_time') { $user_collection = $user_collection->filterRecentEventTime('sign_up', $last_sign_up_times, $value, "Unknown"); } else { $user_collection = $user_collection->filterTextField($name, $value); } } } // Count filtered results $total_filtered = count($user_collection); // Sort if ($sort_order == "desc") { $user_collection = $user_collection->sortByDesc($sort_field, SORT_NATURAL | SORT_FLAG_CASE); } else { $user_collection = $user_collection->sortBy($sort_field, SORT_NATURAL | SORT_FLAG_CASE); } // Paginate if ($page !== null && $size !== null) { $offset = $size * $page; $user_collection = $user_collection->slice($offset, $size); } $result = ["count" => $total, "rows" => $user_collection->values()->toArray(), "count_filtered" => $total_filtered]; //$query = Capsule::getQueryLog(); if ($format == "csv") { $settings = http_build_query($get); $date = date("Ymd"); $this->_app->response->headers->set('Content-Disposition', "attachment;filename={$date}-users-{$settings}.csv"); $this->_app->response->headers->set('Content-Type', 'text/csv; charset=utf-8'); $keys = $user_collection->keys()->toArray(); echo implode(array_keys($result['rows'][0]), ",") . "\r\n"; foreach ($result['rows'] as $row) { echo implode($row, ",") . "\r\n"; } } else { // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content. // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating). $this->_app->response->headers->set('Content-Type', 'application/json; charset=utf-8'); echo json_encode($result, JSON_PRETTY_PRINT); } }
/** * Process UserFrosting registration. This function is copied form UserFrosting class and modified to register the user first * and then save the Open Authentication details * @return \UserFrosting\User */ public function ufRegister() { // POST: user_name, display_name, email, title, password, passwordc, captcha, spiderbro, csrf_token $post = $this->_app->request->post(); // Get the alert message stream $ms = $this->_app->alerts; // Check the honeypot. 'spiderbro' is not a real field, it is hidden on the main page and must be submitted with its default value for this to be processed. if (!$post['spiderbro'] || $post['spiderbro'] != "http://") { error_log("Possible spam received:" . print_r($this->_app->request->post(), true)); $ms->addMessage("danger", "Aww hellllls no!"); $this->_app->halt(500); // Don't let on about why the request failed ;-) } // Load the request schema $requestSchema = new \Fortress\RequestSchema($this->_app->config('schema.path') . "/forms/register.json"); // Set up Fortress to process the request $rf = new \Fortress\HTTPRequestFortress($ms, $requestSchema, $post); // Security measure: do not allow registering new users until the master account has been created. if (!\UserFrosting\User::find($this->_app->config('user_id_master'))) { $ms->addMessageTranslated("danger", "MASTER_ACCOUNT_NOT_EXISTS"); $this->_app->halt(403); } // Check if registration is currently enabled if (!$this->_app->site->can_register) { $ms->addMessageTranslated("danger", "ACCOUNT_REGISTRATION_DISABLED"); $this->_app->halt(403); } // Prevent the user from registering if he/she is already logged in if (!$this->_app->user->isGuest()) { $ms->addMessageTranslated("danger", "ACCOUNT_REGISTRATION_LOGOUT"); $this->_app->halt(200); } // Sanitize data $rf->sanitize(); // Validate, and halt on validation errors. $error = !$rf->validate(true); // Get the filtered data $data = $rf->data(); // Check captcha, if required if ($this->_app->site->enable_captcha == "1") { if (!$data['captcha'] || md5($data['captcha']) != $_SESSION['userfrosting']['captcha']) { $ms->addMessageTranslated("danger", "CAPTCHA_FAIL"); $error = true; } } // Remove captcha, password confirmation from object data $rf->removeFields(['captcha', 'passwordc']); // Perform desired data transformations. Is this a feature we could add to Fortress? $data['display_name'] = trim($data['display_name']); $data['locale'] = $this->_app->site->default_locale; if ($this->_app->site->require_activation) { $data['flag_verified'] = 0; } else { $data['flag_verified'] = 1; } // Check if username or email already exists if (\UserFrosting\User::where('user_name', $data['user_name'])->first()) { $ms->addMessageTranslated("danger", "ACCOUNT_USERNAME_IN_USE", $data); $error = true; } if (\UserFrosting\User::where('email', $data['email'])->first()) { $ms->addMessageTranslated("danger", "ACCOUNT_EMAIL_IN_USE", $data); $error = true; } // Halt on any validation errors if ($error) { $this->_app->halt(400); } // Get default primary group (is_default = GROUP_DEFAULT_PRIMARY) $primaryGroup = \UserFrosting\Group::where('is_default', GROUP_DEFAULT_PRIMARY)->first(); // Check that a default primary group is actually set if (!$primaryGroup) { $ms->addMessageTranslated("danger", "ACCOUNT_REGISTRATION_BROKEN"); error_log("Account registration is not working because a default primary group has not been set."); $this->_app->halt(500); } $data['primary_group_id'] = $primaryGroup->id; // Set default title for new users $data['title'] = $primaryGroup->new_user_title; // Hash password $data['password'] = \UserFrosting\Authentication::hashPassword($data['password']); // Create the user $user = new \UserFrosting\User($data); // Add user to default groups, including default primary group $defaultGroups = \UserFrosting\Group::where('is_default', GROUP_DEFAULT)->get(); $user->addGroup($primaryGroup->id); foreach ($defaultGroups as $group) { $user->addGroup($group->id); } // Create sign-up event $user->newEventSignUp(); // Store new user to database $user->save(); if ($this->_app->site->require_activation) { // Create verification request event $user->newEventVerificationRequest(); $user->save(); // Re-save with verification event // Create and send verification email $twig = $this->_app->view()->getEnvironment(); $template = $twig->loadTemplate("mail/activate-new.twig"); $notification = new \UserFrosting\Notification($template); $notification->fromWebsite(); // Automatically sets sender and reply-to $notification->addEmailRecipient($user->email, $user->display_name, ["user" => $user]); try { $notification->send(); } catch (\phpmailerException $e) { $ms->addMessageTranslated("danger", "MAIL_ERROR"); error_log('Mailer Error: ' . $e->errorMessage()); //$this->_app->halt(500); } $ms->addMessageTranslated("success", "ACCOUNT_REGISTRATION_COMPLETE_TYPE2"); } else { // No activation required $ms->addMessageTranslated("success", "ACCOUNT_REGISTRATION_COMPLETE_TYPE1"); } // Srinivas : The OAuth function will need the user object, so that it can get the ID to save the OAuth record // Invoking this in OAuth to register using return $user; }