| 7 | | class Useraccount extends \BO\Zmsbackend\Query\Base implements \BO\Zmsbackend\Query\MappingInterface |
| 8 | | { |
| 9 | | private const array VALID_PERMISSION_NAMES = [ |
| 10 | | 'appointment', |
| 11 | | 'availability', |
| 12 | | 'calldisplay', |
| 13 | | 'capacityreport', |
| 14 | | 'cherrypick', |
| 15 | | 'cluster', |
| 16 | | 'config', |
| 17 | | 'counter', |
| 18 | | 'customersearch', |
| 19 | | 'dayoff', |
| 20 | | 'department', |
| 21 | | 'emergency', |
| 22 | | 'finishedqueue', |
| 23 | | 'finishedqueuepast', |
| 24 | | 'jurisdiction', |
| 25 | | 'logs', |
| 26 | | 'mailtemplates', |
| 27 | | 'missedqueue', |
| 28 | | 'openqueue', |
| 29 | | 'organisation', |
| 30 | | 'overviewcalendar', |
| 31 | | 'parkedqueue', |
| 32 | | 'restrictedscope', |
| 33 | | 'scope', |
| 34 | | 'source', |
| 35 | | 'statistic', |
| 36 | | 'ticketprinter', |
| 37 | | 'useraccount', |
| 38 | | 'waitingqueue', |
| 39 | | 'superuser', |
| 40 | | ]; |
| 41 | | |
| 42 | | |
| 43 | | |
| 44 | | |
| 45 | | const string TABLE = 'nutzer'; |
| 46 | | const string TABLE_ASSIGNMENT = 'nutzerzuordnung'; |
| 47 | | |
| 48 | | const QUERY_READ_ID_BY_USERNAME = ' |
| 49 | | SELECT user.`NutzerID` AS id |
| 50 | | FROM ' . self::TABLE . ' user |
| 51 | | WHERE |
| 52 | | user.`Name`=? |
| 53 | | '; |
| 54 | | |
| 55 | | const QUERY_WRITE_ASSIGNED_DEPARTMENTS = ' |
| 56 | | REPLACE INTO |
| 57 | | ' . self::TABLE_ASSIGNMENT . ' |
| 58 | | SET |
| 59 | | nutzerid=?, |
| 60 | | behoerdenid=? |
| 61 | | '; |
| 62 | | |
| 63 | | const QUERY_DELETE_ASSIGNED_DEPARTMENTS = ' |
| 64 | | DELETE FROM |
| 65 | | ' . self::TABLE_ASSIGNMENT . ' |
| 66 | | WHERE |
| 67 | | nutzerid=? |
| 68 | | ORDER BY behoerdenid |
| 69 | | '; |
| 70 | | |
| 71 | | const string QUERY_DELETE_USER_ROLES = ' |
| 72 | | DELETE FROM user_role WHERE user_id = ? |
| 73 | | '; |
| 74 | | |
| 75 | | const string QUERY_INSERT_USER_ROLES_BY_NAME = ' |
| 76 | | INSERT INTO user_role (user_id, role_id) |
| 77 | | SELECT ?, r.id FROM role r WHERE r.name IN (:roleNames) |
| 78 | | '; |
| 79 | | |
| 80 | | const QUERY_READ_SUPERUSER_DEPARTMENTS = ' |
| 81 | | SELECT behoerde.`BehoerdenID` AS id |
| 82 | | FROM ' . \BO\Zmsbackend\Department\Repository\Department::TABLE . ' |
| 83 | | ORDER BY behoerde.Name |
| 84 | | '; |
| 85 | | |
| 86 | | const QUERY_READ_ASSIGNED_DEPARTMENTS = ' |
| 87 | | SELECT userAssignment.`behoerdenid` AS id |
| 88 | | FROM ' . self::TABLE_ASSIGNMENT . ' userAssignment |
| 89 | | LEFT JOIN ' . self::TABLE . ' useraccount ON useraccount.Name = :useraccountName |
| 90 | | WHERE |
| 91 | | useraccount.`NutzerID` = userAssignment.`nutzerid` |
| 92 | | ORDER BY userAssignment.`behoerdenid` |
| 93 | | '; |
| 94 | | |
| 95 | | const QUERY_READ_ASSIGNED_DEPARTMENTS_FOR_ALL = ' |
| 96 | | SELECT useraccount.Name as useraccountName, |
| 97 | | userAssignment.`behoerdenid` AS id |
| 98 | | FROM ' . self::TABLE_ASSIGNMENT . ' userAssignment |
| 99 | | LEFT JOIN ' . self::TABLE . ' useraccount ON useraccount.NutzerID = userAssignment.nutzerid |
| 100 | | WHERE |
| 101 | | useraccount.Name IN (:useraccountNames) |
| 102 | | ORDER BY useraccount.Name, userAssignment.`behoerdenid` |
| 103 | | '; |
| 104 | | |
| 105 | | |
| 106 | | |
| 107 | | |
| 108 | | |
| 109 | | protected function permissionExists(string $permissionName): \BO\Zmsbackend\Query\Builder\Expression |
| 110 | | { |
| 111 | | if (!in_array($permissionName, self::VALID_PERMISSION_NAMES, true)) { |
| 112 | | throw new \InvalidArgumentException("Invalid permission name: $permissionName"); |
| 113 | | } |
| 114 | | $quoted = "'" . $permissionName . "'"; |
| 115 | | return self::expression( |
| 116 | | 'EXISTS(' |
| 117 | | . 'SELECT 1 ' |
| 118 | | . 'FROM user_role ur ' |
| 119 | | . 'JOIN role_permission rp ON rp.role_id = ur.role_id ' |
| 120 | | . 'JOIN permission p ON p.id = rp.permission_id ' |
| 121 | | . 'WHERE ur.user_id = useraccount.NutzerID ' |
| 122 | | . 'AND p.name = ' . $quoted |
| 123 | | . ')' |
| 124 | | ); |
| 125 | | } |
| 126 | | |
| 127 | | |
| 128 | | |
| 129 | | |
| 130 | | |
| 131 | | #[\Override] |
| 132 | | public function getEntityMapping() |
| 133 | | { |
| 134 | | return [ |
| 135 | | 'id' => 'useraccount.Name', |
| 136 | | 'password' => 'useraccount.Passworthash', |
| 137 | | 'lastLogin' => 'useraccount.lastUpdate', |
| 138 | | 'roles' => self::expression( |
| 139 | | '(SELECT GROUP_CONCAT(DISTINCT r.name ORDER BY r.name SEPARATOR \',\') ' |
| 140 | | . 'FROM user_role ur ' |
| 141 | | . 'JOIN role r ON r.id = ur.role_id ' |
| 142 | | . 'WHERE ur.user_id = useraccount.NutzerID)' |
| 143 | | ), |
| 144 | | 'permissions__appointment' => $this->permissionExists('appointment'), |
| 145 | | 'permissions__availability' => $this->permissionExists('availability'), |
| 146 | | 'permissions__calldisplay' => $this->permissionExists('calldisplay'), |
| 147 | | 'permissions__capacityreport' => $this->permissionExists('capacityreport'), |
| 148 | | 'permissions__cherrypick' => $this->permissionExists('cherrypick'), |
| 149 | | 'permissions__cluster' => $this->permissionExists('cluster'), |
| 150 | | 'permissions__config' => $this->permissionExists('config'), |
| 151 | | 'permissions__counter' => $this->permissionExists('counter'), |
| 152 | | 'permissions__customersearch' => $this->permissionExists('customersearch'), |
| 153 | | 'permissions__dayoff' => $this->permissionExists('dayoff'), |
| 154 | | 'permissions__department' => $this->permissionExists('department'), |
| 155 | | 'permissions__emergency' => $this->permissionExists('emergency'), |
| 156 | | 'permissions__finishedqueue' => $this->permissionExists('finishedqueue'), |
| 157 | | 'permissions__finishedqueuepast' => $this->permissionExists('finishedqueuepast'), |
| 158 | | 'permissions__jurisdiction' => $this->permissionExists('jurisdiction'), |
| 159 | | 'permissions__logs' => $this->permissionExists('logs'), |
| 160 | | 'permissions__mailtemplates' => $this->permissionExists('mailtemplates'), |
| 161 | | 'permissions__missedqueue' => $this->permissionExists('missedqueue'), |
| 162 | | 'permissions__openqueue' => $this->permissionExists('openqueue'), |
| 163 | | 'permissions__organisation' => $this->permissionExists('organisation'), |
| 164 | | 'permissions__overviewcalendar' => $this->permissionExists('overviewcalendar'), |
| 165 | | 'permissions__parkedqueue' => $this->permissionExists('parkedqueue'), |
| 166 | | 'permissions__restrictedscope' => $this->permissionExists('restrictedscope'), |
| 167 | | 'permissions__scope' => $this->permissionExists('scope'), |
| 168 | | 'permissions__source' => $this->permissionExists('source'), |
| 169 | | 'permissions__statistic' => $this->permissionExists('statistic'), |
| 170 | | 'permissions__ticketprinter' => $this->permissionExists('ticketprinter'), |
| 171 | | 'permissions__useraccount' => $this->permissionExists('useraccount'), |
| 172 | | 'permissions__waitingqueue' => $this->permissionExists('waitingqueue'), |
| 173 | | 'permissions__superuser' => $this->permissionExists('superuser'), |
| 174 | | ]; |
| 175 | | } |
| 176 | | |
| 177 | | public function addConditionLoginName($loginName): static |
| 178 | | { |
| 179 | | $this->query->where('useraccount.Name', '=', $loginName); |
| 180 | | return $this; |
| 181 | | } |
| 182 | | |
| 183 | | public function addConditionUserId($userId): static |
| 184 | | { |
| 185 | | $this->query->where('useraccount.NutzerID', '=', $userId); |
| 186 | | return $this; |
| 187 | | } |
| 188 | | |
| 189 | | public function addConditionPassword($password): static |
| 190 | | { |
| 191 | | $this->query->where('useraccount.Passworthash', '=', $password); |
| 192 | | return $this; |
| 193 | | } |
| 194 | | |
| 195 | | public function addConditionXauthKey(string $xAuthKey): static |
| 196 | | { |
| 197 | | $this->query->where('useraccount.SessionID', '=', $xAuthKey); |
| 198 | | $this->query->where('useraccount.SessionExpiry', '>', date('Y-m-d H:i:s', time() - App::SESSION_DURATION)); |
| 199 | | return $this; |
| 200 | | } |
| 201 | | |
| 202 | | public function addConditionRoleName(string $roleName): self |
| 203 | | { |
| 204 | | $this->setDistinctSelect(); |
| 205 | | |
| 206 | | $this->innerJoin( |
| 207 | | new \BO\Zmsbackend\Query\Alias('user_role', 'useraccount_role'), |
| 208 | | 'useraccount.NutzerID', |
| 209 | | '=', |
| 210 | | 'useraccount_role.user_id' |
| 211 | | ); |
| 212 | | |
| 213 | | $this->innerJoin( |
| 214 | | new \BO\Zmsbackend\Query\Alias('role', 'useraccount_role_name'), |
| 215 | | 'useraccount_role.role_id', |
| 216 | | '=', |
| 217 | | 'useraccount_role_name.id' |
| 218 | | ); |
| 219 | | |
| 220 | | $this->query->where('useraccount_role_name.name', '=', $roleName); |
| 221 | | |
| 222 | | return $this; |
| 223 | | } |
| 224 | | |
| 225 | | public function addConditionSearch($queryString, bool $orWhere = false): static |
| 226 | | { |
| 227 | | $condition = function (\BO\Zmsbackend\Query\Builder\ConditionBuilder $query) use ($queryString) { |
| 228 | | $queryString = trim($queryString); |
| 229 | | $query->orWith('useraccount.NutzerID', 'LIKE', "%$queryString%"); |
| 230 | | $query->orWith('useraccount.Name', 'LIKE', "%$queryString%"); |
| 231 | | }; |
| 232 | | if ($orWhere) { |
| 233 | | $this->query->orWhere($condition); |
| 234 | | } else { |
| 235 | | $this->query->where($condition); |
| 236 | | } |
| 237 | | return $this; |
| 238 | | } |
| 239 | | |
| 240 | | |
| 241 | | |
| 242 | | |
| 243 | | |
| 244 | | public function reverseEntityMapping(\BO\Zmsentities\Useraccount $entity): array |
| 245 | | { |
| 246 | | $data = array(); |
| 247 | | $data['Name'] = $entity->id; |
| 248 | | $data['Passworthash'] = (isset($entity->password)) ? $entity->password : null; |
| 249 | | $data['BehoerdenID'] = 0; |
| 250 | | $department = $entity->getDepartmentList()->getFirst(); |
| 251 | | if (!$entity->isSuperUser() && $department !== null) { |
| 252 | | $data['BehoerdenID'] = $department->id; |
| 253 | | } |
| 254 | | |
| 255 | | $data['notrufinitiierung'] = 0; |
| 256 | | $data['notrufantwort'] = 0; |
| 257 | | |
| 258 | | $data = array_filter($data, function ($value) { |
| 259 | | return ($value !== null && $value !== false); |
| 260 | | }); |
| 261 | | return $data; |
| 262 | | } |
| 263 | | |
| 264 | | #[\Override] |
| 265 | | public function postProcess($data) |
| 266 | | { |
| 267 | | $data[$this->getPrefixed("lastLogin")] = ('0000-00-00' != $data[$this->getPrefixed("lastLogin")]) ? |
| 268 | | strtotime($data[$this->getPrefixed("lastLogin")]) : |
| 269 | | null; |
| 270 | | |
| 271 | | $rolesKey = $this->getPrefixed('roles'); |
| 272 | | $rawRoles = $data[$rolesKey] ?? null; |
| 273 | | if ($rawRoles === null || $rawRoles === '') { |
| 274 | | $data[$rolesKey] = []; |
| 275 | | } elseif (is_string($rawRoles)) { |
| 276 | | $data[$rolesKey] = array_values(array_filter(array_map('trim', explode(',', $rawRoles)), function ($v) { |
| 277 | | return $v !== ''; |
| 278 | | })); |
| 279 | | } |
| 280 | | |
| 281 | | $permissionsPrefix = $this->getPrefixed('permissions__'); |
| 282 | | foreach ($data as $key => $value) { |
| 283 | | if (0 === strpos($key, $permissionsPrefix)) { |
| 284 | | $data[$key] = (bool) $value; |
| 285 | | } |
| 286 | | } |
| 287 | | |
| 288 | | return $data; |
| 289 | | } |
| 290 | | |
| 291 | | public function addConditionDepartmentIds(array $departmentIds): static |
| 292 | | { |
| 293 | | $this->setDistinctSelect(); |
| 294 | | $this->innerJoin( |
| 295 | | new \BO\Zmsbackend\Query\Alias(static::TABLE_ASSIGNMENT, 'useraccount_department'), |
| 296 | | 'useraccount.NutzerID', |
| 297 | | '=', |
| 298 | | 'useraccount_department.nutzerid' |
| 299 | | ); |
| 300 | | $this->query->where('useraccount_department.behoerdenid', 'IN', $departmentIds); |
| 301 | | return $this; |
| 302 | | } |
| 303 | | |
| 304 | | public function addConditionDepartmentIdsAndSearch(array $departmentIds, $queryString = null, bool $orWhere = false): self |
| 305 | | { |
| 306 | | $this->addConditionDepartmentIds($departmentIds); |
| 307 | | |
| 308 | | if ($queryString) { |
| 309 | | $this->addConditionSearch($queryString, $orWhere); |
| 310 | | } |
| 311 | | |
| 312 | | return $this; |
| 313 | | } |
| 314 | | |
| 315 | | public function addConditionExcludeSuperusers(): self |
| 316 | | { |
| 317 | | $this->setDistinctSelect(); |
| 318 | | |
| 319 | | $this->innerJoin( |
| 320 | | new \BO\Zmsbackend\Query\Alias('user_role', 'exclude_superuser_user_role'), |
| 321 | | 'useraccount.NutzerID', |
| 322 | | '=', |
| 323 | | 'exclude_superuser_user_role.user_id' |
| 324 | | ); |
| 325 | | |
| 326 | | $this->innerJoin( |
| 327 | | new \BO\Zmsbackend\Query\Alias('role', 'exclude_superuser_role'), |
| 328 | | 'exclude_superuser_user_role.role_id', |
| 329 | | '=', |
| 330 | | 'exclude_superuser_role.id' |
| 331 | | ); |
| 332 | | |
| 333 | | $this->query->where('exclude_superuser_role.name', '!=', 'system_admin'); |
| 334 | | |
| 335 | | return $this; |
| 336 | | } |
| 337 | | |
| 338 | | public function addOrderByName(): self |
| 339 | | { |
| 340 | | $this->query->orderBy('useraccount.Name', 'ASC'); |
| 341 | | return $this; |
| 342 | | } |
| 343 | | |
| 344 | | |
| 345 | | |
| 346 | | |
| 347 | | |
| 348 | | |
| 349 | | public function addConditionWorkstationAccess($workstationUserId, array $workstationDepartmentIds, bool $isWorkstationSuperuser = false): self |
| 350 | | { |
| 351 | | |
| 352 | | if ($isWorkstationSuperuser) { |
| 353 | | return $this; |
| 354 | | } |
| 355 | | |
| 356 | | $this->addConditionExcludeSuperusers(); |
| 357 | | |
| 358 | | |
| 359 | | if (empty($workstationDepartmentIds)) { |
| 360 | | return $this; |
| 361 | | } |
| 362 | | |
| 363 | | |
| 364 | | $this->setDistinctSelect(); |
| 365 | | $this->innerJoin( |
| 366 | | new \BO\Zmsbackend\Query\Alias(static::TABLE_ASSIGNMENT, 'useraccount_department'), |
| 367 | | 'useraccount.NutzerID', |
| 368 | | '=', |
| 369 | | 'useraccount_department.nutzerid' |
| 370 | | ); |
| 371 | | |
| 372 | | |
| 373 | | $this->query->where('useraccount_department.behoerdenid', 'IN', $workstationDepartmentIds); |
| 374 | | |
| 375 | | return $this; |
| 376 | | } |
| 377 | | } |