1e5a6b4d4SGreg Roach<?php 2e5a6b4d4SGreg Roach/** 3e5a6b4d4SGreg Roach * webtrees: online genealogy 4e5a6b4d4SGreg Roach * Copyright (C) 2019 webtrees development team 5e5a6b4d4SGreg Roach * This program is free software: you can redistribute it and/or modify 6e5a6b4d4SGreg Roach * it under the terms of the GNU General Public License as published by 7e5a6b4d4SGreg Roach * the Free Software Foundation, either version 3 of the License, or 8e5a6b4d4SGreg Roach * (at your option) any later version. 9e5a6b4d4SGreg Roach * This program is distributed in the hope that it will be useful, 10e5a6b4d4SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 11e5a6b4d4SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12e5a6b4d4SGreg Roach * GNU General Public License for more details. 13e5a6b4d4SGreg Roach * You should have received a copy of the GNU General Public License 14e5a6b4d4SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>. 15e5a6b4d4SGreg Roach */ 16e5a6b4d4SGreg Roachdeclare(strict_types=1); 17e5a6b4d4SGreg Roach 18e5a6b4d4SGreg Roachnamespace Fisharebest\Webtrees\Services; 19e5a6b4d4SGreg Roach 20e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Auth; 21e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\Individual; 22e5a6b4d4SGreg Roachuse Fisharebest\Webtrees\User; 23e5a6b4d4SGreg Roachuse Illuminate\Database\Capsule\Manager as DB; 24e5a6b4d4SGreg Roachuse Illuminate\Database\Query\JoinClause; 25e5a6b4d4SGreg Roachuse Illuminate\Support\Collection; 26e5a6b4d4SGreg Roach 27e5a6b4d4SGreg Roach/** 28e5a6b4d4SGreg Roach * Functions for managing users. 29e5a6b4d4SGreg Roach */ 30e5a6b4d4SGreg Roachclass UserService 31e5a6b4d4SGreg Roach{ 32e5a6b4d4SGreg Roach /** 33e5a6b4d4SGreg Roach * Find the user with a specified user_id. 34e5a6b4d4SGreg Roach * 35e5a6b4d4SGreg Roach * @param int|null $user_id 36e5a6b4d4SGreg Roach * 37e5a6b4d4SGreg Roach * @return User|null 38e5a6b4d4SGreg Roach */ 39e5a6b4d4SGreg Roach public function find($user_id) 40e5a6b4d4SGreg Roach { 41e5a6b4d4SGreg Roach return app('cache.array')->rememberForever(__CLASS__ . $user_id, function () use ($user_id) { 42e5a6b4d4SGreg Roach return DB::table('user') 43e5a6b4d4SGreg Roach ->where('user_id', '=', $user_id) 44e5a6b4d4SGreg Roach ->get() 45e5a6b4d4SGreg Roach ->map(User::rowMapper()) 46e5a6b4d4SGreg Roach ->first(); 47e5a6b4d4SGreg Roach }); 48e5a6b4d4SGreg Roach } 49e5a6b4d4SGreg Roach 50e5a6b4d4SGreg Roach /** 51e5a6b4d4SGreg Roach * Find the user with a specified email address. 52e5a6b4d4SGreg Roach * 53e5a6b4d4SGreg Roach * @param string $email 54e5a6b4d4SGreg Roach * 55e5a6b4d4SGreg Roach * @return User|null 56e5a6b4d4SGreg Roach */ 57e5a6b4d4SGreg Roach public function findByEmail($email) 58e5a6b4d4SGreg Roach { 59e5a6b4d4SGreg Roach return DB::table('user') 60e5a6b4d4SGreg Roach ->where('email', '=', $email) 61e5a6b4d4SGreg Roach ->get() 62e5a6b4d4SGreg Roach ->map(User::rowMapper()) 63e5a6b4d4SGreg Roach ->first(); 64e5a6b4d4SGreg Roach } 65e5a6b4d4SGreg Roach 66e5a6b4d4SGreg Roach /** 67e5a6b4d4SGreg Roach * Find the user with a specified user_name or email address. 68e5a6b4d4SGreg Roach * 69e5a6b4d4SGreg Roach * @param string $identifier 70e5a6b4d4SGreg Roach * 71e5a6b4d4SGreg Roach * @return User|null 72e5a6b4d4SGreg Roach */ 73e5a6b4d4SGreg Roach public function findByIdentifier($identifier) 74e5a6b4d4SGreg Roach { 75e5a6b4d4SGreg Roach return DB::table('user') 76e5a6b4d4SGreg Roach ->where('user_name', '=', $identifier) 77e5a6b4d4SGreg Roach ->orWhere('email', '=', $identifier) 78e5a6b4d4SGreg Roach ->get() 79e5a6b4d4SGreg Roach ->map(User::rowMapper()) 80e5a6b4d4SGreg Roach ->first(); 81e5a6b4d4SGreg Roach } 82e5a6b4d4SGreg Roach 83e5a6b4d4SGreg Roach /** 84e5a6b4d4SGreg Roach * Find the user(s) with a specified genealogy record. 85e5a6b4d4SGreg Roach * 86e5a6b4d4SGreg Roach * @param Individual $individual 87e5a6b4d4SGreg Roach * 88e5a6b4d4SGreg Roach * @return Collection|User[] 89e5a6b4d4SGreg Roach */ 90e5a6b4d4SGreg Roach public function findByIndividual(Individual $individual): Collection 91e5a6b4d4SGreg Roach { 92e5a6b4d4SGreg Roach return DB::table('user') 93e5a6b4d4SGreg Roach ->join('user_gedcom_setting', 'user_gedcom_setting.user_id', '=', 'user.user_id') 94e5a6b4d4SGreg Roach ->where('gedcom_id', '=', $individual->tree()->id()) 95e5a6b4d4SGreg Roach ->where('setting_value', '=', $individual->xref()) 96e5a6b4d4SGreg Roach ->where('setting_name', '=', 'gedcomid') 97e5a6b4d4SGreg Roach ->select(['user.*']) 98e5a6b4d4SGreg Roach ->get() 99e5a6b4d4SGreg Roach ->map(User::rowMapper()); 100e5a6b4d4SGreg Roach } 101e5a6b4d4SGreg Roach 102e5a6b4d4SGreg Roach /** 103e5a6b4d4SGreg Roach * Find the user with a specified user_name. 104e5a6b4d4SGreg Roach * 105e5a6b4d4SGreg Roach * @param string $user_name 106e5a6b4d4SGreg Roach * 107e5a6b4d4SGreg Roach * @return User|null 108e5a6b4d4SGreg Roach */ 109e5a6b4d4SGreg Roach public function findByUserName($user_name) 110e5a6b4d4SGreg Roach { 111e5a6b4d4SGreg Roach return DB::table('user') 112e5a6b4d4SGreg Roach ->where('user_name', '=', $user_name) 113e5a6b4d4SGreg Roach ->get() 114e5a6b4d4SGreg Roach ->map(User::rowMapper()) 115e5a6b4d4SGreg Roach ->first(); 116e5a6b4d4SGreg Roach } 117e5a6b4d4SGreg Roach 118e5a6b4d4SGreg Roach /** 119e5a6b4d4SGreg Roach * Get a list of all users. 120e5a6b4d4SGreg Roach * 121e5a6b4d4SGreg Roach * @return Collection|User[] 122e5a6b4d4SGreg Roach */ 123e5a6b4d4SGreg Roach public function all(): Collection 124e5a6b4d4SGreg Roach { 125e5a6b4d4SGreg Roach return DB::table('user') 126e5a6b4d4SGreg Roach ->where('user_id', '>', 0) 127e5a6b4d4SGreg Roach ->orderBy('real_name') 128e5a6b4d4SGreg Roach ->get() 129e5a6b4d4SGreg Roach ->map(User::rowMapper()); 130e5a6b4d4SGreg Roach } 131e5a6b4d4SGreg Roach 132e5a6b4d4SGreg Roach /** 133e5a6b4d4SGreg Roach * Get a list of all administrators. 134e5a6b4d4SGreg Roach * 135e5a6b4d4SGreg Roach * @return Collection|User[] 136e5a6b4d4SGreg Roach */ 137e5a6b4d4SGreg Roach public function administrators(): Collection 138e5a6b4d4SGreg Roach { 139e5a6b4d4SGreg Roach return DB::table('user') 140e5a6b4d4SGreg Roach ->join('user_setting', function (JoinClause $join): void { 141e5a6b4d4SGreg Roach $join 142e5a6b4d4SGreg Roach ->on('user_setting.user_id', '=', 'user.user_id') 143e5a6b4d4SGreg Roach ->where('user_setting.setting_name', '=', 'canadmin') 144e5a6b4d4SGreg Roach ->where('user_setting.setting_value', '=', '1'); 145e5a6b4d4SGreg Roach }) 146e5a6b4d4SGreg Roach ->where('user.user_id', '>', 0) 147e5a6b4d4SGreg Roach ->orderBy('real_name') 148e5a6b4d4SGreg Roach ->select(['user.*']) 149e5a6b4d4SGreg Roach ->get() 150e5a6b4d4SGreg Roach ->map(User::rowMapper()); 151e5a6b4d4SGreg Roach } 152e5a6b4d4SGreg Roach 153e5a6b4d4SGreg Roach /** 154e5a6b4d4SGreg Roach * Get a list of all managers. 155e5a6b4d4SGreg Roach * 156e5a6b4d4SGreg Roach * @return Collection|User[] 157e5a6b4d4SGreg Roach */ 158e5a6b4d4SGreg Roach public function managers(): Collection 159e5a6b4d4SGreg Roach { 160e5a6b4d4SGreg Roach return DB::table('user') 161e5a6b4d4SGreg Roach ->join('user_gedcom_setting', function (JoinClause $join): void { 162e5a6b4d4SGreg Roach $join 163e5a6b4d4SGreg Roach ->on('user_gedcom_setting.user_id', '=', 'user.user_id') 164e5a6b4d4SGreg Roach ->where('user_gedcom_setting.setting_name', '=', 'canedit') 165e5a6b4d4SGreg Roach ->where('user_gedcom_setting.setting_value', '=', 'admin'); 166e5a6b4d4SGreg Roach }) 167e5a6b4d4SGreg Roach ->where('user.user_id', '>', 0) 168e5a6b4d4SGreg Roach ->orderBy('real_name') 169e5a6b4d4SGreg Roach ->select(['user.*']) 170e5a6b4d4SGreg Roach ->get() 171e5a6b4d4SGreg Roach ->map(User::rowMapper()); 172e5a6b4d4SGreg Roach } 173e5a6b4d4SGreg Roach 174e5a6b4d4SGreg Roach /** 175e5a6b4d4SGreg Roach * Get a list of all moderators. 176e5a6b4d4SGreg Roach * 177e5a6b4d4SGreg Roach * @return Collection|User[] 178e5a6b4d4SGreg Roach */ 179e5a6b4d4SGreg Roach public function moderators(): Collection 180e5a6b4d4SGreg Roach { 181e5a6b4d4SGreg Roach return DB::table('user') 182e5a6b4d4SGreg Roach ->join('user_gedcom_setting', function (JoinClause $join): void { 183e5a6b4d4SGreg Roach $join 184e5a6b4d4SGreg Roach ->on('user_gedcom_setting.user_id', '=', 'user.user_id') 185e5a6b4d4SGreg Roach ->where('user_gedcom_setting.setting_name', '=', 'canedit') 186e5a6b4d4SGreg Roach ->where('user_gedcom_setting.setting_value', '=', 'accept'); 187e5a6b4d4SGreg Roach }) 188e5a6b4d4SGreg Roach ->where('user.user_id', '>', 0) 189e5a6b4d4SGreg Roach ->orderBy('real_name') 190e5a6b4d4SGreg Roach ->select(['user.*']) 191e5a6b4d4SGreg Roach ->get() 192e5a6b4d4SGreg Roach ->map(User::rowMapper()); 193e5a6b4d4SGreg Roach } 194e5a6b4d4SGreg Roach 195e5a6b4d4SGreg Roach /** 196e5a6b4d4SGreg Roach * Get a list of all verified users. 197e5a6b4d4SGreg Roach * 198e5a6b4d4SGreg Roach * @return Collection|User[] 199e5a6b4d4SGreg Roach */ 200e5a6b4d4SGreg Roach public function unapproved(): Collection 201e5a6b4d4SGreg Roach { 202e5a6b4d4SGreg Roach return DB::table('user') 203e5a6b4d4SGreg Roach ->join('user_setting', function (JoinClause $join): void { 204e5a6b4d4SGreg Roach $join 205e5a6b4d4SGreg Roach ->on('user_setting.user_id', '=', 'user.user_id') 206e5a6b4d4SGreg Roach ->where('user_setting.setting_name', '=', 'verified_by_admin') 207e5a6b4d4SGreg Roach ->where('user_setting.setting_value', '=', '0'); 208e5a6b4d4SGreg Roach }) 209e5a6b4d4SGreg Roach ->where('user.user_id', '>', 0) 210e5a6b4d4SGreg Roach ->orderBy('real_name') 211e5a6b4d4SGreg Roach ->select(['user.*']) 212e5a6b4d4SGreg Roach ->get() 213e5a6b4d4SGreg Roach ->map(User::rowMapper()); 214e5a6b4d4SGreg Roach } 215e5a6b4d4SGreg Roach 216e5a6b4d4SGreg Roach /** 217e5a6b4d4SGreg Roach * Get a list of all verified users. 218e5a6b4d4SGreg Roach * 219e5a6b4d4SGreg Roach * @return Collection|User[] 220e5a6b4d4SGreg Roach */ 221e5a6b4d4SGreg Roach public function unverified(): Collection 222e5a6b4d4SGreg Roach { 223e5a6b4d4SGreg Roach return DB::table('user') 224e5a6b4d4SGreg Roach ->join('user_setting', function (JoinClause $join): void { 225e5a6b4d4SGreg Roach $join 226e5a6b4d4SGreg Roach ->on('user_setting.user_id', '=', 'user.user_id') 227e5a6b4d4SGreg Roach ->where('user_setting.setting_name', '=', 'verified') 228e5a6b4d4SGreg Roach ->where('user_setting.setting_value', '=', '0'); 229e5a6b4d4SGreg Roach }) 230e5a6b4d4SGreg Roach ->where('user.user_id', '>', 0) 231e5a6b4d4SGreg Roach ->orderBy('real_name') 232e5a6b4d4SGreg Roach ->select(['user.*']) 233e5a6b4d4SGreg Roach ->get() 234e5a6b4d4SGreg Roach ->map(User::rowMapper()); 235e5a6b4d4SGreg Roach } 236e5a6b4d4SGreg Roach 237e5a6b4d4SGreg Roach /** 238e5a6b4d4SGreg Roach * Get a list of all users who are currently logged in. 239e5a6b4d4SGreg Roach * 240e5a6b4d4SGreg Roach * @return Collection|User[] 241e5a6b4d4SGreg Roach */ 242e5a6b4d4SGreg Roach public function allLoggedIn(): Collection 243e5a6b4d4SGreg Roach { 244e5a6b4d4SGreg Roach return DB::table('user') 245e5a6b4d4SGreg Roach ->join('session', 'session.user_id', '=', 'user.user_id') 246e5a6b4d4SGreg Roach ->where('user.user_id', '>', 0) 247e5a6b4d4SGreg Roach ->orderBy('real_name') 248e5a6b4d4SGreg Roach ->select(['user.*']) 249e5a6b4d4SGreg Roach ->distinct() 250e5a6b4d4SGreg Roach ->get() 251e5a6b4d4SGreg Roach ->map(User::rowMapper()); 252e5a6b4d4SGreg Roach } 253e5a6b4d4SGreg Roach 254e5a6b4d4SGreg Roach /** 255e5a6b4d4SGreg Roach * Create a new user. 256e5a6b4d4SGreg Roach * The calling code needs to check for duplicates identifiers before calling 257e5a6b4d4SGreg Roach * this function. 258e5a6b4d4SGreg Roach * 259e5a6b4d4SGreg Roach * @param string $user_name 260e5a6b4d4SGreg Roach * @param string $real_name 261e5a6b4d4SGreg Roach * @param string $email 262e5a6b4d4SGreg Roach * @param string $password 263e5a6b4d4SGreg Roach * 264e5a6b4d4SGreg Roach * @return User 265e5a6b4d4SGreg Roach */ 266*c65e00b4SGreg Roach public static function create(string $user_name, string $real_name, string $email, string $password): User 267e5a6b4d4SGreg Roach { 268e5a6b4d4SGreg Roach DB::table('user')->insert([ 269e5a6b4d4SGreg Roach 'user_name' => $user_name, 270e5a6b4d4SGreg Roach 'real_name' => $real_name, 271e5a6b4d4SGreg Roach 'email' => $email, 272e5a6b4d4SGreg Roach 'password' => password_hash($password, PASSWORD_DEFAULT), 273e5a6b4d4SGreg Roach ]); 274e5a6b4d4SGreg Roach 275e5a6b4d4SGreg Roach $user_id = (int) DB::connection()->getPdo()->lastInsertId(); 276e5a6b4d4SGreg Roach 277e5a6b4d4SGreg Roach return new User($user_id, $user_name, $real_name, $email); 278e5a6b4d4SGreg Roach } 279e5a6b4d4SGreg Roach 280e5a6b4d4SGreg Roach /** 281e5a6b4d4SGreg Roach * Delete a user 282e5a6b4d4SGreg Roach * 283e5a6b4d4SGreg Roach * @param User $user 284e5a6b4d4SGreg Roach * 285e5a6b4d4SGreg Roach * @return void 286e5a6b4d4SGreg Roach */ 287e5a6b4d4SGreg Roach public function delete(User $user) 288e5a6b4d4SGreg Roach { 289e5a6b4d4SGreg Roach // Don't delete the logs, just set the user to null. 290e5a6b4d4SGreg Roach DB::table('log') 291e5a6b4d4SGreg Roach ->where('user_id', '=', $user->id()) 292e5a6b4d4SGreg Roach ->update(['user_id' => null]); 293e5a6b4d4SGreg Roach 294e5a6b4d4SGreg Roach // Take over the user’s pending changes. (What else could we do with them?) 295e5a6b4d4SGreg Roach DB::table('change') 296e5a6b4d4SGreg Roach ->where('user_id', '=', $user->id()) 297e5a6b4d4SGreg Roach ->where('status', '=', 'rejected') 298e5a6b4d4SGreg Roach ->delete(); 299e5a6b4d4SGreg Roach 300e5a6b4d4SGreg Roach DB::table('change') 301e5a6b4d4SGreg Roach ->where('user_id', '=', $user->id()) 302e5a6b4d4SGreg Roach ->update(['user_id' => Auth::id()]); 303e5a6b4d4SGreg Roach 304e5a6b4d4SGreg Roach // Take over the user's contact details 305e5a6b4d4SGreg Roach DB::table('gedcom_setting') 306e5a6b4d4SGreg Roach ->where('setting_value', '=', $user->id()) 307e5a6b4d4SGreg Roach ->whereIn('setting_name', ['CONTACT_USER_ID', 'WEBMASTER_USER_ID']) 308e5a6b4d4SGreg Roach ->update(['setting_value' => Auth::id()]); 309e5a6b4d4SGreg Roach 310e5a6b4d4SGreg Roach // Delete settings and preferences 311e5a6b4d4SGreg Roach DB::table('block_setting') 312e5a6b4d4SGreg Roach ->join('block', 'block_setting.block_id', '=', 'block.block_id') 313e5a6b4d4SGreg Roach ->where('user_id', '=', $user->id()) 314e5a6b4d4SGreg Roach ->delete(); 315e5a6b4d4SGreg Roach 316e5a6b4d4SGreg Roach DB::table('block')->where('user_id', '=', $user->id())->delete(); 317e5a6b4d4SGreg Roach DB::table('user_gedcom_setting')->where('user_id', '=', $user->id())->delete(); 318e5a6b4d4SGreg Roach DB::table('user_setting')->where('user_id', '=', $user->id())->delete(); 319e5a6b4d4SGreg Roach DB::table('message')->where('user_id', '=', $user->id())->delete(); 320e5a6b4d4SGreg Roach DB::table('user')->where('user_id', '=', $user->id())->delete(); 321e5a6b4d4SGreg Roach } 322e5a6b4d4SGreg Roach} 323