chuckymendoza Posted March 20, 2015 Posted March 20, 2015 Hello together, I had a deeper look into the forum but didn’t found anything, so I like to ask the following simple question. Is there a module or a simple technique to export all users from the backend into a file? Afterwards, it should be possible to import the users again. I have a ProcessWire installation on a dev server and I don’t like the idea to add all users again by hand on the live server Thanks so much for your ideas. -Thomas
LostKobrakai Posted March 20, 2015 Posted March 20, 2015 While it's certainly possible it's not as easy as you may think it is. Passwords are stored as hashes in the database. ProcessWire will never store the plain text password. The hashing is dependent on the salt value stored in the config.php. The salt is generated as part of the installation process and therefore your live installation may have another salt value as the dev one. If this is the case it means all the passwords of imported users would be invalid after moving them. What you can do is to copy the whole users database table and copy over the salt value, too. As long as all hashes of user passwords are generated with the same salt value you can exchange users as you wish. But if you have users in both installations, where the passwords where saved with different salt values, you can not move the passwords over from one installation to another. You would need to change/update the passwords by hand in this case. Everything besides the passwords shouldn't be a problem. 6
gebeer Posted November 23, 2015 Posted November 23, 2015 I am trying to find a solution for having same users with same passwords in 2 different PW installs and came across this thread. How would I export the user table? There is no such table as users are pages. So I would need to construct a MySQL query that gets all pages with user template and also grab required fields name, pass, email. Then the other tricky part would be to import that into the new PW install. Is there a PW API side solution that also tranfers the password hashes to the new install?
LostKobrakai Posted November 23, 2015 Posted November 23, 2015 I think you should be able to read the hashed password to export them, e.g. with the PageActionExportCsv which comes with listerpro. I'm just not sure if those hashed passwords would be rehashed, when importing the csv.
gebeer Posted November 23, 2015 Posted November 23, 2015 @LostKobraKai Thank you. I will look into the Lister Pro Action. Meanwhile I decided to export the users including their hashed password to csv with // get desired users $array = []; $us = $users->find("roles=frontend"); foreach ($us as $key => $u) { $u->of(false); $array[$key] = ["id" => $u->id, "name" => $u->name, "email" => $u->email, "pass" => $u->pass]; } // write to file $fp = fopen('./inc/users.csv', 'w'); $i = 0; foreach ($array as $fields) { // Add headings to the first line. if($i==0) fputcsv($fp, array_keys($fields), ","); fputcsv($fp, $fields); $i++; } fclose($fp); Now I am looking into a way to import the users in the new PW install via API and in that process bypassing the regular $user->pass method for setting the password. So that I can store the hashed password as is during import. Then I'd only need to copy over the salt from the original PW install and the users should be able to login. But when looking at the ___setPass($value) method in /wire/core/Password.php, I am not sure how to hook into it and make it just save the supplied value. Also, looking at /wire/core/User.php, I don't see how this is connected to the Password class or vice versa. 1
LostKobrakai Posted November 23, 2015 Posted November 23, 2015 The user class is just an more specific page class, so it shouldn't have any correlation with the password, as 'pass' is a field with the FieldtypePassword.
gebeer Posted November 23, 2015 Posted November 23, 2015 Am I on the right path at all when I try and replace the ___setPass($value) method so that it sets $this->data['hash'] = $value (value that gets passed in to the method)?
LostKobrakai Posted November 23, 2015 Posted November 23, 2015 I've not much overview over the specifics, but it sounds like the way to go.
Mackski Posted December 7, 2015 Posted December 7, 2015 Hey gebeer, I'm trying to extend your function for admin only, by adding a button to the users screen: /processwire/access/users/Do you know where exactly I would create my hook point?I'm a little stumped, while adding hooks to ProcessPageEdit are relativley easy, I'm yet to see an example for the users section of processwire.
LostKobrakai Posted December 7, 2015 Posted December 7, 2015 ProcessUser is the module, which handles this section of the admin, and it does by itself use ProcessPageEdit for the user editing, so you'll probably don't need different hooks, but just a check if the current edited page is a user.
Mackski Posted December 7, 2015 Posted December 7, 2015 Thanks Lost, but I'm still Lost! Still no idea how to hook prior to output to add the new button, this is what I have: $this->addHookBefore('ProcessUser::render', $this, 'usersAddButtons');
LostKobrakai Posted December 7, 2015 Posted December 7, 2015 ProcessPageEdit::buildForm is most likely the hook you want to use if you want to add things to the page edit form.
Mackski Posted December 7, 2015 Posted December 7, 2015 There is no form on this page to hook to: /processwire/access/users/ Hence the problem.
LostKobrakai Posted December 7, 2015 Posted December 7, 2015 For that page ProcessUser is inheriting the usage of a customized Lister from ProcessPageType, so you probably need to hook some of the ProcessPageType::execute… methods.
Mackski Posted December 8, 2015 Posted December 8, 2015 I was unable to hook to this page, so ended up creating a custom admin page to support a button to export users via CSV.Seems overkill, and I'm sure there are other senarios which may warrant additional buttons such as: Selecting all users for another operation (copy to clipboard) or email all users etc.It would be nice to find out the appropriate method to hook to 1
alexm Posted August 2, 2023 Posted August 2, 2023 Not sure if this is still a thing that people require, or this should really be posted here for security reasons, (if so, feel free to remove) but here's a solution that is tested and works. It relies on both instances using the same user salt. $usersArray = []; foreach($users as $user) { if($user->isSuperuser() || $user->name == 'guest') continue; // Skip the admin and guest user $roles = []; foreach ($user->roles as $role) { $roles[] = $role->name; } $usersArray[] = [ 'username' => $user->name, 'email' => $user->email, 'roles' => $roles, 'pass_hash' => $user->pass->hash, 'pass_salt' => $user->pass->salt, ]; } $usersJson = json_encode($usersArray); echo $usersJson; Then copy the output JSON array and then drop it in $json variable in the next part on the other end. $json = ''; $importUsers = json_decode($json, true); foreach ($importUsers as $iUser) { $userExists = $users->get("name={$iUser['username']},email={$iUser['email']}"); if ($userExists->id == 0) { echo "{$iUser['username']} should be added<br>"; $u = new User(); $u->name = $iUser['username']; $u->email = $iUser['email']; if (count($iUser['roles'])) { foreach ($iUser['roles'] as $role) { $u->addRole($role); } } $u->pass->hash = $iUser['pass_hash']; $u->pass->salt = $iUser['pass_salt']; $u->save(); echo "User: $u->name added successfully<br><br>"; } } Obvs add any other field data you want to export and import.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now