Files
thetool/application/User/UserController.php
2025-08-07 13:05:07 +00:00

639 lines
19 KiB
PHP

<?php
/**
* Description of UserController
*
* @author fronk
*/
class UserController extends mfBaseController
{
private $me;
protected function init($request = null)
{
$this->needlogin = true;
$me = new User();
$me->loadMe(true);
$this->me = $me;
$this->layout()->set("me", $me);
if (!$me->isAdmin()) {
// all users can call non-action methods
if ($this->action != "" || $request != null) {
$this->redirect("Dashboard");
}
}
}
protected function indexAction($request)
{
if (!$this->isAdmin()) {
throw new Exception("Forbidden", 403);
}
Helper::renderVue($this, "User", "Benutzer", [
"IS_ADMIN" => $this->me->isAdmin(),
"USERS" => array_map(fn($user) => [
"username" => $user->username,
"name" => $user->name,
"address" => ($user->address->company) ? $user->address->company : $user->address->getFullName(),
"email" => $user->email,
"mobile" => $user->mobile,
"twofactor" => [1 => 'Mail', 2 => 'SMS'][$user->twofactor] ?? 'N/A',
"isAdmin" => $user->isAdmin(),
"isTechnician" => $user->is("Technician"),
"isActive" => $user->active,
"id" => $user->id
], UserModel::getAll()),
"ADD_URL" => self::getUrl("User", "add"),
"EDIT_URL" => self::getUrl("User", "edit"),
"IMPERSONATE_URL" => self::getUrl("User", "impersonate"),
]);
}
protected function addAction($request)
{
if (!$this->isAdmin()) {
throw new Exception("Forbidden", 403);
}
$this->layout()->setTemplate('User/Form');
$roles = TT_NETWORK_ROLES_WITH_OWNER;
$roles[] = "systemowner";
$addresses = AddressModel::search(["addresstype" => $roles]);
$this->layout()->set("addresses", $addresses);
if ($this->request->address_id) {
$this->layout()->set("address_id", $this->request->address_id);
}
}
protected function editAction($request)
{
if (!$this->isAdmin()) {
throw new Exception("Forbidden", 403);
}
$this->layout()->setTemplate('User/Form');
$id = $request['id'];
if (!is_numeric($id) || $id <= 0) {
throw new Exception("User $id not found", 604);
}
$user = new User($id);
$this->layout()->set('user', $user);
$addresses = AddressModel::getAll();
$this->layout()->set("addresses", $addresses);
}
protected function generateApikeyAction($request)
{
if (!$this->isAdmin()) {
$this->redirect("Dashboard");
}
$id = $request['id'];
if (!is_numeric($id) || $id < 1) {
$this->layout()->setFlash("User nicht gefunden.", "error");
$this->redirect("User");
}
$user = new User($id);
if (!$user->id) {
$this->layout()->setFlash("User nicht gefunden.", "error");
$this->redirect("User");
}
$user->apikey = $user->createApiKey();
$user->save();
$this->layout()->setFlash("API Key erfolgreich generiert.", "success");
$this->redirect("User", "edit", ['id' => $id]);
}
protected function profileAction($request)
{
}
protected function saveAction()
{
$r = $this->request;
$id = $r->id;
if (!$this->isAdmin()) {
$id = $this->me->id;
$request['username'] = $this->me->username;
unset($r->address_id);
}
if (!$id && !$r->username) {
self::redirect('User');
}
$user = new User($id);
// check if new user already exits
if ($this->isAdmin() && !$r->id) {
$tu = new User();
$tu->loadByUsername($r->username);
if ($tu->id) {
$this->layout()->setFlash("Benutzer mit diesem Benutzername bereits vorhanden!", "error");
$this->redirect("User");
}
}
$user->active = $r->active === "true" ? 1 : 0;
if (!$user->permissions) {
$user->permissions = new WorkerPermission();
}
if ($r->username) {
$user->username = $r->username;
}
if ($r->name) {
$user->name = $r->name;
}
if ($r->email) {
$user->email = $r->email;
}
if ($r->mobile) {
$user->mobile = $r->mobile;
} else {
$user->mobile = NULL;
}
if ($this->isAdmin()) {
if ($r->address_id) {
$user->address_id = intval($r->address_id);
//var_dump($user);exit;
$address = new Address($user->address_id);
if (!$address->id) {
throw new Exception("Unbekannte Firma/Person");
}
} else {
$user->address_id = null;
}
// 2fa required
if($r->twofactorrequired == "true") {
$user->twofactorrequired = 1;
} else {
$user->twofactorrequired = 0;
}
}
if ($r->password) {
if ($r->password === $r->password2) {
$user->password = mfLoginController::generatePasswordHash($r->password);
} else {
$this->layout()->setFlash("Passwörter stimmen nicht überein!", "error");
}
}
$user->edit_by = $this->me->id;
if (!$id) {
$user->create_by = $this->me->id;
}
$id = $user->save();
if ($this->isAdmin()) {
if ($r->admin == "true" || $user->id == 1) {
$user->permissions->admin = "true";
} else {
$user->permissions->admin = "false";
}
if ($r->employee == "true") {
$user->permissions->employee = "true";
} else {
$user->permissions->employee = "false";
}
if ($r->technician == "true") {
$user->permissions->technician = "true";
} else {
$user->permissions->technician = "false";
}
if ($r->preorderfront == "true") {
$user->permissions->preorderfront = "true";
} else {
$user->permissions->preorderfront = "false";
}
if ($r->preorderlogistics == "true") {
$user->permissions->preorderlogistics = "true";
} else {
$user->permissions->preorderlogistics = "false";
}
if ($r->preorderaddressreporting == "true") {
$user->permissions->preorderaddressreporting = "true";
} else {
$user->permissions->preorderaddressreporting = "false";
}
if ($r->preorderreadonly == "true") {
$user->permissions->preorderreadonly = "true";
} else {
$user->permissions->preorderreadonly = "false";
}
// set can permissions
$user->permissions->canBuilding = "false";
$user->permissions->canPipework = "false";
$user->permissions->canLinework = "false";
$user->permissions->canPatching = "false";
$user->permissions->canFilestore = "false";
$user->permissions->canCpeprovisioning = "false";
$user->permissions->canCpeshipping = "false";
$user->permissions->canVoipnumbering = "false";
$user->permissions->canPreorder = "false";
$user->permissions->canPreorderpricing = "false";
$user->permissions->canPreorderpricingReadonly = "false";
$user->permissions->canPreorderbilling = "false";
$user->permissions->canPreorderbillingReadonly = "false";
$user->permissions->canOrder = "false";
$user->permissions->canBilling = "false";
$user->permissions->canFibu = "false";
$user->permissions->canStatistics = "false";
$user->permissions->canWarehouseAdmin = "false";
$user->permissions->canWarehouseEShop = "false";
$user->permissions->canWarehouseUser = "false";
$user->permissions->canADBExtended = "false";
$user->permissions->canAssetAdmin = "false";
$user->permissions->canRMLAdmin = "false";
if($r->get("can") && is_array($r->can)) {
foreach($r->can as $key => $can) {
//var_dump($key . "=> ".$can);
if($can) {
$user->permissions->{"can$key"} = "true";
}
}
}
$user->permissions->save();
// save networks
$pn = $user->getFlag("preorder_networks");
if (is_array($r->preorder_networks) && count($r->preorder_networks)) {
$pn->value(json_encode($r->preorder_networks));
$pn->save();
$user->permissions->canPreorder = "true";
$user->permissions->save();
} else {
$pn->delete();
}
$constructionConsentProjects = $user->getFlag("constructionConsent_projects");
if (is_array($r->constructionconsent_projects) && count($r->constructionconsent_projects)) {
$constructionConsentProjects->value(json_encode($r->constructionconsent_projects));
$constructionConsentProjects->save();
} else {
$constructionConsentProjects->delete();
}
// employee number
$enum = new WorkerFlag($user->id, "employee_number");
if($r->employee_number && $user->permissions->employee == "true") {
$enum->value($r->employee_number);
$enum->save();
} else {
$enum->delete();
}
// workerflag for project_api_key
$pak = new WorkerFlag($user->id, "project_api_key");
if($r->project_api_key) {
$pak->value($r->project_api_key);
$pak->save();
} else {
$pak->delete();
}
// vodia identity data
$vid = new WorkerFlag($user->id, "vodia_identity_domain");
if($r->vodia_identity_domain) {
$vid->value($r->vodia_identity_domain);
$vid->save();
} else {
$vid->delete();
}
$viu = new WorkerFlag($user->id, "vodia_identity_username");
if($r->vodia_identity_username) {
$viu->value($r->vodia_identity_username);
$viu->save();
} else {
$viu->delete();
}
$vdi = new WorkerFlag($user->id, "vodia_identity_default");
if($r->vodia_identity_default) {
$vdi->value($r->vodia_identity_default);
$vdi->save();
} else {
$vdi->delete();
}
}
$this->layout()->setFlash("Benutzer gespeichert.", "success");
self::redirect('User');
}
protected function deleteAction($request)
{
$this->layout()->setFlash("nope");
$this->redirect("User");
if (!$this->isAdmin()) {
$this->redirect("Dashboard");
}
$id = $request['id'];
if (!is_numeric($id) || $id <= 0) {
throw new Exception("User $id not found", 604);
}
$user = new User($id);
if ($user->id == $id) {
$user->delete();
}
self::redirect("User");
}
protected function pwchangeAction($request)
{
$me = new User();
$me->loadMe();
$pw1 = $request['password'];
$pw2 = $request['password2'];
if (!$pw1 == $pw2) {
throw new Exception("Passwords don't match! Password change aborted.");
}
if (strlen($pw1) < 8) {
throw new Exception("Passwords must be 8 characters minimum!");
}
if ($pw1 == "12345678" || $pw1 == "123456789" || $pw1 == "password" || $pw1 == "passwort") {
throw new Exception("Be a little more creative with your password please...");
}
$me->password = mfLoginController::generatePasswordHash($pw1);
$me->save();
$this->redirect("Dashboard");
}
public function getUsers()
{
$users = array();
$res = $this->db()->select(MFUSERTABLE, '*', '1=1 ORDER BY username');
if ($this->db()->num_rows($res)) {
while ($data = $this->db()->fetch_object($res)) {
$users[$data->id] = new User($data);
}
}
return $users;
}
private function isAdmin()
{
$me = new User();
$this->layout->set("me", $me);
$me->loadMe();
return $me->isAdmin();
}
protected function apiAction() {
$do = $this->request->do;
$data = [];
$me = new User();
$me->loadMe();
$return = false;
switch($do) {
case "sse":
$me->is(["Admin"]) && $return = $this->startSuperexpertApi();
break;
case "ese":
$me->is(["Admin"]) && $return = $this->extendSuperexpertApi();
break;
case "endse":
$me->is(["Admin"]) && $return = $this->endSuperexpertApi();
break;
case "getVodiaIdentity":
$return = $this->getVodiaIdentityApi();
break;
case "setVodiaIdentity":
$return = $this->setVodiaIdentityApi();
break;
case "getVodiaCall":
$return = $this->getVodiaCallApi();
break;
default:
$return = false;
}
if(!is_array($return) || !count($return)) {
$data = ["status" => "error"];
$this->returnJson($data);
}
$data['status'] = "OK";
$data['result'] = $return;
$this->returnJson($data);
}
private function getVodiaIdentityApi() {
if(!ENABLE_VODIA_IDENTITY_SWITCHER) {
return ["enabled" => false];
}
$me = new User();
$me->loadMe();
$vodia = new Vodia_Api(VODIA_API_URL, VODIA_API_ADMIN_USER, VODIA_API_ADMIN_PASS);
$domain = $me->getFlag("vodia_identity_domain")->value();
$username = $me->getFlag("vodia_identity_username")->value();
$default = $me->getFlag("vodia_identity_default")->value();
if(!$domain || !$username || !$default) {
return ["enabled" => false];
}
$current = $vodia->getUsersetting($domain, $username, "ani");
if($current) {
if(str_replace(" ", "", $current) == str_replace(" ", "", $default)) {
$current = $default;
}
} else {
$current = $default;
}
return [
"enabled" => true,
"domain" => $domain,
"username" => $username,
"default" => $default,
"default_number" => str_replace(" ", "", $default),
"current" => $current,
"identities" => VODIA_OUTBOUND_IDENTITIES,
];
}
private function setVodiaIdentityApi() {
if(!ENABLE_VODIA_IDENTITY_SWITCHER) {
return ["enabled" => false];
}
$number = $this->request->number;
if(!$number) {
return false;
}
// expects number to start with +
if(!substr($number, 0, 1) == "+") {
return false;
}
$me = new User();
$me->loadMe();
$domain = $me->getFlag("vodia_identity_domain")->value();
$username = $me->getFlag("vodia_identity_username")->value();
if(!$domain || !$username) {
return ["enabled" => false];
}
$vodia = new Vodia_Api(VODIA_API_URL, VODIA_API_ADMIN_USER, VODIA_API_ADMIN_PASS);
if(!$vodia->setUsersettings($domain, $username, ["ani" => $number])) {
return false;
}
return ["enabled" => true, "number" => $number];
}
private function getVodiaCallApi() {
if(!ENABLE_VODIA_IDENTITY_SWITCHER) {
return ["enabled" => false];
}
$domain = $this->me->getFlag("vodia_identity_domain")->value();
$username = $this->me->getFlag("vodia_identity_username")->value();
if(!$domain || !$username) {
return ["enabled" => false];
}
$vodia = new Vodia_Api(VODIA_API_URL, VODIA_API_ADMIN_USER, VODIA_API_ADMIN_PASS);
$calls = $vodia->getActiveCalls($domain, $username);
if(!$calls) {
return ["enabled" => true, "calls" => []];
}
$from = null;
foreach($calls as $call) {
if(isset($call['from'])) {
$from = $call['from'];
if(preg_match('/<sip:([^@]+)@/', $from, $m)) {
$from = $m[1];
} elseif(preg_match('/<([^>]+)>/', $from, $m)) {
$from = $m[1];
} else {
$from = str_replace('"', '', $from);
}
break; // only return the first call's from number
}
}
return ["enabled" => true, "number" => $from];
}
private function startSuperexpertApi() {
$me = new User();
$me->loadMe();
if($me->superexpertEnabled() ) {
// superexpert mode started already
return false;
}
$me->superexpertStart(1800);
return ["valid_to" => $me->getFlag("superexpert_lock_date")->value()];
}
private function extendSuperexpertApi() {
$me = new User();
$me->loadMe();
if(!$me->superexpertEnabled() ) {
// superexpert mode must be started already
$this->log->debug("se not started");
return false;
}
$this->log->debug("ese");
$me->superexpertExtend(1800);
return ["valid_to" => $me->getFlag("superexpert_lock_date")->value()];
}
private function endSuperexpertApi() {
$me = new User();
$me->loadMe();
if($me->superexpertEnabled() ) {
$me->superexpertStop();
}
return ["valid_to" => null];
}
protected function getByIdAction() {
$id = $this->request->id;
$user = new User($id);
$this->returnJson($user->toArray());
}
protected function impersonateAction() {
if(!$this->me->isAdmin() || $this->me->address_id != 1) {
header("HTTP/1.1 403 Forbidden");
exit;
}
if($this->request->unimpersonate) {
unset($_SESSION[MFAPPNAME.'_impersonate']);
$this->redirect("User");
}
if(!$this->request->username || strlen($this->request->username) < 3) {
header("HTTP/1.1 500 Internal Server Error");
exit;
}
$_SESSION[MFAPPNAME.'_impersonate'] = $this->request->username;
$this->redirect("Dashboard");
}
}