Compare commits

..

9 Commits

Author SHA1 Message Date
Paolo 290d617e0f Merge branch 'master' into feature-52366/CI_LoginAsUID_verbessern 2026-07-09 10:47:31 +02:00
Paolo 01ea24f5bd Merge branch 'master' into feature-52366/CI_LoginAsUID_verbessern 2026-06-11 11:25:13 +02:00
Paolo 16b649c951 Merge branch 'master' into feature-52366/CI_LoginAsUID_verbessern 2026-04-27 13:07:23 +02:00
Paolo 8a567416db Merge branch 'master' into feature-52366/CI_LoginAsUID_verbessern 2026-03-24 09:36:54 +01:00
Paolo a3dffd1fc2 Login AS GUI now uses the UID and not the person_id 2026-03-06 12:16:19 +01:00
Paolo 2460253c19 Merge branch 'master' into feature-52366/CI_LoginAsUID_verbessern 2026-02-23 14:17:36 +01:00
Paolo 62ad0dcd47 GUI improvements 2025-10-21 11:48:10 +02:00
Paolo 9355ee740d LoginAs: added search by person id and sorted results by surname and name 2025-10-20 12:34:08 +02:00
Paolo 2484bf1217 - Added LoginAs to the menu
- Added new page to see your credentials and to get the credentials of someone else using autocomplete (searches by uid, name or surname)
- Refactored the login page on CI side
2025-10-20 11:40:10 +02:00
23 changed files with 599 additions and 342 deletions
+43 -19
View File
@@ -1,11 +1,27 @@
<?php
// Header menu
/**
* Copyright (C) 2025 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if(defined('CIS4') && CIS4) {
$root = APP_ROOT;
} else {
$root = CIS_ROOT;
}
$root = CIS_ROOT;
if (defined('CIS4') && CIS4) $root = APP_ROOT;
// --------------------------------------------------------------------------------------------------------------------
// Head menu
$config['navigation_header'] = array(
'*' => array(
@@ -202,13 +218,20 @@ $config['navigation_header'] = array(
'sort' => 20,
'requiredPermissions' => 'system/developer:r'
),
'anrechnungen' => array(
'link' => site_url('lehre/anrechnung/AdminAnrechnung'),
'description' => 'Anrechnungen',
'expand' => true,
'sort' => 30,
'requiredPermissions' => 'lehre/anrechnungszeitfenster:rw'
),
'anrechnungen' => array(
'link' => site_url('lehre/anrechnung/AdminAnrechnung'),
'description' => 'Anrechnungen',
'expand' => true,
'sort' => 30,
'requiredPermissions' => 'lehre/anrechnungszeitfenster:rw'
),
'loginas' => array(
'link' => site_url('system/Login/loginAs'),
'description' => 'Login as',
'expand' => true,
'sort' => 40,
'requiredPermissions' => 'admin:rw'
),
'dashboardadmin' => array(
'link' => site_url('dashboard/Admin'),
'description' => 'Dashboard Admin',
@@ -236,12 +259,12 @@ $config['navigation_menu']['Vilesci/index'] = array(
);
$config['navigation_menu']['Vilesci/index'] = array(
'dashboard' => array(
'link' => '#',
'description' => 'Dashboard',
'icon' => 'dashboard',
'sort' => 1
)
'dashboard' => array(
'link' => '#',
'description' => 'Dashboard',
'icon' => 'dashboard',
'sort' => 1
)
);
$config['navigation_menu']['organisation/Reihungstest/index'] = array(
@@ -383,3 +406,4 @@ $config['navigation_menu']['apps'] = [
'requiredPermissions' => array('lehre/lehrauftrag_bestellen:r', 'lehre/lehrauftrag_erteilen:r')
]
];
+9 -28
View File
@@ -45,7 +45,7 @@ $config['person'] = [
'field' => 'kontakt',
'join' => [
'table' => "public.tbl_kontakt",
'on' => "kontakttyp IN ('telefon', 'so.tel', 'mobil', 'firmenhandy') AND tbl_kontakt.person_id = tbl_person.person_id"
'on' => "kontakttyp IN ('telefon', 'so.tel', 'mobil') AND tbl_kontakt.person_id = tbl_person.person_id"
],
"1-n" => true
],
@@ -360,10 +360,6 @@ $config['employee'] = [
'comparison' => 'equals',
'field' => "mitarbeiter_uid"
],
'personalnummer' => [
'comparison' => 'equal-int',
'field' => "personalnummer"
],
'vorname' => [
'alias' => ['firstname'],
'comparison' => 'similar',
@@ -419,27 +415,12 @@ $config['employee'] = [
'tel' => [
'alias' => ['phone', 'telefon'],
'comparison' => 'similar',
'field' => 'kontakt',
'prepare' => "employee_tel (mitarbeiter_uid, kontakt) AS (
SELECT m.mitarbeiter_uid,
TRIM(COALESCE(k.kontakt, '') || ' ' || COALESCE(m.telefonklappe, ''))
FROM public.tbl_mitarbeiter m
LEFT JOIN public.tbl_kontakt k
ON k.standort_id = m.standort_id
AND k.kontakttyp = 'telefon'
UNION
SELECT m.mitarbeiter_uid, k.kontakt
FROM public.tbl_mitarbeiter m
JOIN public.tbl_benutzer b ON b.uid = m.mitarbeiter_uid
JOIN public.tbl_kontakt k
ON k.person_id = b.person_id
AND k.kontakttyp IN ('telefon', 'so.tel', 'mobil', 'firmenhandy')
)",
'field' => "TRIM(COALESCE(kontakt, '') || ' ' || COALESCE(telefonklappe, ''))",
'join' => [
'table' => "employee_tel",
'using' => "mitarbeiter_uid"
'table' => "public.tbl_kontakt",
'on' => "kontakttyp = 'telefon' AND tbl_kontakt.standort_id = tbl_mitarbeiter.standort_id"
],
'1-n' => true
"1-n" => true
],
'pid' => [
'alias' => ['person_id'],
@@ -490,7 +471,6 @@ $config['employee'] = [
],
'resultfields' => [
"b.uid",
"m.personalnummer",
"p.person_id",
"(p.vorname || ' ' || p.nachname) AS name",
"ARRAY(
@@ -532,6 +512,7 @@ $config['employee'] = [
) k ON (k.standort_id = m.standort_id)"
];
// TODO(chris): move to searchpv21.php
$config['unassigned_employee'] = $config['employee'];
$config['unassigned_employee']['alias'] = ['mitarbeiter_ohne_zuordnung'];
$config['unassigned_employee']['prepare'] = "unassigned_employee AS (
@@ -543,7 +524,7 @@ $config['unassigned_employee']['prepare'] = "unassigned_employee AS (
AND (datum_von IS NULL OR datum_von <= NOW())
AND (datum_bis IS NULL OR datum_bis >= NOW())
)
WHERE tbl_benutzerfunktion.uid IS NULL
WHERE tbl_benutzerfunktion.bezeichnung IS NULL
UNION
SELECT tbl_mitarbeiter.*
FROM public.tbl_mitarbeiter
@@ -553,10 +534,10 @@ $config['unassigned_employee']['prepare'] = "unassigned_employee AS (
AND (datum_von IS NULL OR datum_von <= NOW())
AND (datum_bis IS NULL OR datum_bis >= NOW())
)
WHERE tbl_benutzerfunktion.uid IS NULL
WHERE tbl_benutzerfunktion.bezeichnung IS NULL
)";
$config['unassigned_employee']['table'] = "unassigned_employee";
$config['unassigned_employee']['searchfields']['tel'] = "
$config['unassigned_employee']['searchfields']['tel']['join']['on'] = "
kontakttyp = 'telefon'
AND tbl_kontakt.standort_id = unassigned_employee.standort_id
";
-34
View File
@@ -1,34 +0,0 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
$CI =& get_instance();
$config['person'] = $CI->config->item('person', 'search');
$config['employee'] = $CI->config->item('employee', 'search');
$config['employee']['resultjoin'] = "
JOIN public.tbl_mitarbeiter m USING (mitarbeiter_uid)
JOIN public.tbl_benutzer b ON (b.uid = m.mitarbeiter_uid AND b.aktiv = true)
JOIN public.tbl_person p USING(person_id)
LEFT JOIN (
SELECT kontakt, standort_id
FROM public.tbl_kontakt
WHERE kontakttyp = 'telefon'
) k ON (k.standort_id = m.standort_id)";
$config['unassigned_employee'] = $CI->config->item('unassigned_employee', 'search');
$config['unassigned_employee']['resultjoin'] = "
JOIN public.tbl_mitarbeiter m USING (mitarbeiter_uid)
JOIN public.tbl_benutzer b ON (b.uid = m.mitarbeiter_uid AND b.aktiv = true)
JOIN public.tbl_person p USING(person_id)
LEFT JOIN (
SELECT kontakt, standort_id
FROM public.tbl_kontakt
WHERE kontakttyp = 'telefon'
) k ON (k.standort_id = m.standort_id)";
$config['room'] = $CI->config->item('room', 'search');
$config['organisationunit'] = $CI->config->item('organisationunit', 'search');
-1
View File
@@ -7,7 +7,6 @@ $CI =& get_instance();
$config['employee'] = $CI->config->item('employee', 'search');
unset($config['employee']['searchfields']['tel']);
$config['employee']['resultjoin'] = "
JOIN public.tbl_mitarbeiter m USING (mitarbeiter_uid)
JOIN public.tbl_benutzer b ON (b.uid = m.mitarbeiter_uid AND b.aktiv = true)
@@ -0,0 +1,137 @@
<?php
/**
* Copyright (C) 2025 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*
*/
class Login extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct(array(
'loginLDAP' => self::PERM_ANONYMOUS,
'loginASByUid' => 'admin:rw',
'loginASByPersonId' => 'admin:rw',
'whoAmI' => self::PERM_ANONYMOUS,
'searchUser' => 'admin:rw'
));
}
/**
* Called with HTTP POST via ajax to login using the LDAP authentication
*/
public function loginLDAP()
{
$username = $this->input->post('username');
$password = $this->input->post('password');
$this->load->library('AuthLib', array(false)); // without authentication otherwise loooooop!
$login = $this->authlib->loginLDAP($username, $password);
// If login is success then retrieves the desired page
if (isSuccess($login)) $this->terminateWithSuccess($this->authlib->getLandingPage());
$this->terminateWithError(getError($login)); // returns the error code
}
/**
* Called with HTTP POST via ajax to login as another user specified by uid
*/
public function loginASByUid()
{
$uid = $this->input->post('uid');
// With authentication -> you must be already logged to gain another identity
$this->load->library('AuthLib');
$loginAS = $this->authlib->loginASByUID($uid);
// Got it!
if (isSuccess($loginAS)) $this->terminateWithSuccess(true);
// Returns the error code
$this->terminateWithError(getError($loginAS));
}
/**
* Called with HTTP POST via ajax to login as another user specified by person id
*/
public function loginASByPersonId()
{
$person_id = $this->input->post('person_id');
// With authentication -> you must be already logged to gain another identity
$this->load->library('AuthLib');
$loginAS = $this->authlib->loginASByPersonId($person_id);
// Got it!
if (isSuccess($loginAS)) $this->terminateWithSuccess(true);
// Returns the error code
$this->terminateWithError(getError($loginAS));
}
/**
* Called with HTTP GET via ajax to show which login cretentials are in use
*/
public function whoAmI()
{
// With authentication -> you must be already logged to gain another identity
$this->load->library('AuthLib');
$this->terminateWithSuccess($this->authlib->getAuthObj());
}
/**
* Search for a user in database checking the name, surname or uid
*/
public function searchUser()
{
$query = strtolower('%'.$this->input->get('query').'%');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
$dataset = $this->BenutzerModel->execReadOnlyQuery('
SELECT p.person_id,
b.uid,
p.nachname,
p.vorname,
b.uid,
p.person_id || \' - \' || b.uid || \' - \' || p.nachname || \' \' || p.vorname AS label
FROM public.tbl_person p
LEFT JOIN public.tbl_benutzer b ON(b.person_id = p.person_id)
WHERE b.aktiv = TRUE
AND (p.nachname ILIKE ? OR p.vorname ILIKE ? OR b.uid ILIKE ? OR p.person_id::text LIKE ?)
ORDER BY p.nachname, p.vorname
',
array($query, $query, $query, $query)
);
if (isError($dataset)) $this->terminateWithError(getError($dataset));
$this->terminateWithSuccess($dataset);
}
}
@@ -37,8 +37,7 @@ class Searchbar extends FHCAPI_Controller
parent::__construct([
'search' => self::PERM_LOGGED,
'searchCis' => self::PERM_LOGGED,
'searchStv' => self::PERM_LOGGED,
'searchPV' => self::PERM_LOGGED
'searchStv' => self::PERM_LOGGED
]);
$this->load->model('system/Webservicelog_model', 'WebservicelogModel');
@@ -88,15 +87,6 @@ class Searchbar extends FHCAPI_Controller
return $this->searchAdvanced([ 'config' => 'searchstv' ]);
}
/**
* Gets a JSON body via HTTP POST and provides the parameters
*/
public function searchPV()
{
return $this->searchAdvanced([ 'config' => 'searchPV' ]);
}
/**
* Gets a JSON body via HTTP POST and provides the parameters
*/
+26 -69
View File
@@ -1,4 +1,20 @@
<?php
/**
* Copyright (C) 2025 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (!defined('BASEPATH')) exit('No direct script access allowed');
@@ -8,12 +24,14 @@ if (!defined('BASEPATH')) exit('No direct script access allowed');
class Login extends FHC_Controller
{
/**
*
* Object initialization
*/
public function __construct()
{
parent::__construct();
}
{
parent::__construct(array(
'loginAs' => 'admin:rw'
));
}
/**
* Displays a login page with username and password
@@ -24,72 +42,11 @@ class Login extends FHC_Controller
}
/**
* Called with HTTP POST via ajax to login using the LDAP authentication
* Displays a login page with username and password
*/
public function loginLDAP()
{
$username = $this->input->post('username');
$password = $this->input->post('password');
$this->load->library('AuthLib', array(false)); // without authentication otherwise loooooop!
$login = $this->authlib->loginLDAP($username, $password);
if (isSuccess($login))
{
$this->outputJsonSuccess($this->authlib->getLandingPage()); // if login is success then retrieves the desired page
}
else
{
$this->outputJsonError(getCode($login)); // returns the error code
}
}
/**
* Called with HTTP POST via ajax to login as another user specified by uid
*/
public function loginASByUid()
{
$uid = $this->input->get('uid');
// With authentication -> you must be already logged to gain another identity
$this->load->library('AuthLib');
$loginAS = $this->authlib->loginASByUID($uid);
$this->outputJson($loginAS); // returns the error code
}
/**
* Called with HTTP POST via ajax to login as another user specified by person id
*/
public function loginASByPersonId()
{
$person_id = $this->input->get('person_id');
// With authentication -> you must be already logged to gain another identity
$this->load->library('AuthLib');
$loginAS = $this->authlib->loginASByPersonId($person_id);
if (isSuccess($loginAS))
{
$this->outputJsonSuccess(true); // obtained!
}
else
{
$this->outputJsonSuccess(getCode($loginAS)); // returns the error code
};
}
/**
* To login into the system with email and code as credentials
*/
public function emailCode()
{
}
/**
* To login into the system using SSO
*/
public function sso()
public function loginAs()
{
$this->load->view('system/login/loginAs');
}
}
@@ -122,47 +122,6 @@ class Studiensemester_model extends DB_Model
return $this->execQuery($query, array($studiensemester_kurzbz, $limit));
}
/**
* Returns the current study semester and the previous semesters of the same type (SS/WS).
*
* Example:
* - SS2026, limit 3: SS2026, SS2025, SS2024
* - WS2025, limit 2: WS2025, WS2024
*
* @param $studiensemester_kurzbz
* @param $limit
*/
public function getPreviousSameSemesterFrom($studiensemester_kurzbz, $limit = 1)
{
$qry = '
SELECT
studiensemester_kurzbz,
start,
ende
FROM
public.tbl_studiensemester
WHERE
SUBSTRING(studiensemester_kurzbz FROM 1 FOR 2) = SUBSTRING(? FROM 1 FOR 2)
AND start <= (
SELECT start
FROM public.tbl_studiensemester
WHERE studiensemester_kurzbz = ?
)
ORDER BY
start DESC
LIMIT ?
';
return $this->execQuery($qry,
[
$studiensemester_kurzbz,
$studiensemester_kurzbz,
$limit
]
);
}
/**
* getNearest
*/
@@ -260,6 +260,7 @@ class Benutzerfunktion_model extends DB_Model
return $this->execQuery($query, $parameters_array);
}
/**
* Get active Kompetenzfeldleitung bei UID.
*
@@ -295,6 +296,7 @@ class Benutzerfunktion_model extends DB_Model
return $this->execQuery($query, $parameters_array);
}
public function insertBenutzerfunktion($Json)
{
unset($Json['benutzerfunktion_id']);
@@ -0,0 +1,37 @@
<?php
/**
* Copyright (C) 2025 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
$includesArray = array(
'title' => 'Login',
'axios027' => true,
'bootstrap5' => true,
'fontawesome6' => true,
'vue3' => true,
'primevue3' => true,
'phrases' => array('uid', 'global'),
'navigationcomponent' => true,
'customJSModules' => array('public/js/LoginAs.js'),
);
$this->load->view('templates/FHC-Header', $includesArray);
?>
<div id="main"></div>
<?php $this->load->view('templates/FHC-Footer', $includesArray); ?>
@@ -1,44 +1,39 @@
<?php
$this->load->view(
'templates/FHC-Header',
array(
'title' => 'Login',
'jquery3' => true,
'jqueryui1' => true,
'bootstrap3' => true,
'fontawesome4' => true,
'sbadmintemplate3' => true,
'ajaxlib' => true,
'dialoglib' => true,
'customCSSs' => 'public/css/Login.css',
'customJSs' => 'public/js/Login.js'
)
);
/**
* Copyright (C) 2025 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
$includesArray = array(
'title' => 'Login',
'axios027' => true,
'bootstrap5' => true,
'fontawesome6' => true,
'vue3' => true,
'filtercomponent' => true,
'navigationcomponent' => true,
'tabulator5' => true,
'primevue3' => true,
'phrases' => array('uid', 'global'),
'customJSModules' => array('public/js/Login.js'),
);
$this->load->view('templates/FHC-Header', $includesArray);
?>
<div id="main"></div>
<div class="login-form">
<?php $this->load->view('templates/FHC-Footer', $includesArray); ?>
<p class="text-center">
<img src="<?php echo base_url('public/images/logo-300x160.png'); ?>" >
</p>
<br>
<div class="form-group">
<input id="username" type="text" class="form-control" placeholder="Username" required="required">
</div>
<div class="form-group">
<input id="password" type="password" class="form-control" placeholder="Password" required="required">
</div>
<div class="form-group">
<button id="btnLogin" ype="submit" class="btn btn-primary btn-block">Log in</button>
</div>
<p class="text-center"><a href="#">Forgot Password?</a></p>
</div>
<?php $this->load->view('templates/FHC-Footer'); ?>
+73 -49
View File
@@ -1,55 +1,79 @@
/**
* To login via LDAP
* Copyright (C) 2025 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
function loginLDAP()
{
// Ajax call to login with LDAP
FHC_AjaxClient.ajaxCallPost(
"system/Login/loginLDAP",
{
username: $("#username").val(),
password: $("#password").val()
},
{
successCallback: function(data, textStatus, jqXHR) {
if (FHC_AjaxClient.isError(data))
{
if (FHC_AjaxClient.getError(data) == 10)
import PluginsPhrasen from '../js/plugins/Phrasen.js';
import ApiLogin from '../js/api/factory/login.js';
const loginApp = Vue.createApp({
data: function() {
return {
username: '',
password: ''
};
},
components: {
},
methods: {
loginLDAP: function() {
this.$api
.call(ApiLogin.loginLDAP({
username: this.username,
password: this.password
}))
.then((response) => {
// If property data exists
if (Object.hasOwn(response, 'data'))
{
FHC_DialogLib.alertError("Username not foud");
// If property data is a string
if (typeof response.data === 'string' || response.data instanceof String)
{
// If property data is a valid URL
try {
let url = new URL(response.data);
// If here the URL contained in response.data is fine
// and can be used to switch to the landing page
document.location.href = response.data;
} catch (_) {}
}
}
if (FHC_AjaxClient.getError(data) == 2)
{
FHC_DialogLib.alertError("Wrong password");
}
}
else
{
$(location).attr("href", FHC_AjaxClient.getData(data));
}
},
errorCallback: function(jqXHR, textStatus, errorThrown) {
FHC_DialogLib.alertError(textStatus);
}
}
);
}
/**
* When JQuery is up
*/
$(document).ready(function() {
$("#btnLogin").click(loginLDAP);
$("#username").keydown(function(e) {
if (e.keyCode == 13) loginLDAP();
})
$("#password").keydown(function(e) {
if (e.keyCode == 13) loginLDAP();
})
})
.catch((error) => {
console.error(error);
});
}
},
template: `
<div class="d-flex align-items-center justify-content-center">
<div>
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" name="username" id="username" v-model="username">
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" name="password" id="password" v-model="password">
</div>
<div class="d-flex align-items-center justify-content-center">
<button type="button" class="btn btn-primary" @click="loginLDAP">Login</button>
</div>
</div>
</div>
`
});
loginApp.use(PluginsPhrasen).mount('#main');
+168
View File
@@ -0,0 +1,168 @@
/**
* Copyright (C) 2025 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import PluginsPhrasen from '../js/plugins/Phrasen.js';
import ApiLogin from '../js/api/factory/login.js';
import {CoreNavigationCmpt} from '../js/components/navigation/Navigation.js';
import PvAutoComplete from "../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js";
const loginAsApp = Vue.createApp({
data: function() {
return {
person_id: '',
username: '',
surname: '',
name: '',
selectedUser: null,
filteredUsers: [],
appSideMenuEntries: {}
};
},
components: {
CoreNavigationCmpt,
PvAutoComplete
},
methods: {
loginAs: function() {
if (this.selectedUser != null)
{
this.$api
.call(ApiLogin.loginASByUid({
uid: this.selectedUser.uid
}))
.then((response) => {
location.reload();
})
.catch((error) => {
console.error(error);
});
}
},
logout: function() {
this.$api
.call(ApiLogin.logout())
.then((response) => {
location.reload();
})
.catch((error) => {
console.error(error);
});
},
searchUser: function(event) {
if (event.query.length >= 3)
{
this.$api
.call(ApiLogin.searchUser(event.query))
.then(result => {
this.filteredUsers = result.data.retval;
})
.catch((error) => {
console.error(error);
});
}
}
},
mounted: function() {
this.$api
.call(ApiLogin.whoAmI())
.then((response) => {
// If property data exists
if (Object.hasOwn(response, 'data'))
{
if (response.data != null && Object.hasOwn(response.data, 'person_id'))
{
this.person_id = response.data.person_id;
this.username = response.data.username;
this.surname = response.data.surname;
this.name = response.data.name;
}
else
{
this.person_id = 'Not logged';
this.username = 'Not logged';
this.surname = 'Not logged';
this.name = 'Not logged';
}
}
})
.catch((error) => {
console.error(error);
});
},
template: `
<!-- Navigation component -->
<core-navigation-cmpt v-bind:add-side-menu-entries="appSideMenuEntries"></core-navigation-cmpt>
<div style="width: 700px !important">
<div class="card" style="padding: 20px;">
<div class="mb-3">
Who am I?
</div>
<div class="mb-3">
<div class="d-inline-flex align-items-center">
<label for="person_id" class="form-label" style="width: 150px !important">Person ID</label>
<input type="text" style="width: 400px !important" disabled="disabled" class="form-control" id="person_id" v-model="person_id">
</div>
</div>
<div class="mb-3">
<div class="d-inline-flex align-items-center">
<label for="username" class="form-label" style="width: 150px !important">UID</label>
<input type="text" style="width: 400px !important" disabled="disabled" class="form-control" id="username" v-model="username">
</div>
</div>
<div class="mb-3">
<div class="d-inline-flex align-items-center">
<label for="surname" class="form-label" style="width: 150px !important">Surname</label>
<input type="text" style="width: 400px !important" disabled="disabled" class="form-control" id="surname" v-model="surname">
</div>
</div>
<div class="mb-3">
<div class="d-inline-flex align-items-center">
<label for="name" class="form-label" style="width: 150px !important">Name</label>
<input type="text" style="width: 400px !important" disabled="disabled" class="form-control" id="name" v-model="name">
</div>
</div>
<div class="d-flex align-items-center justify-content-center">
<button type="button" class="btn btn-primary" @click="logout">Logout</button>
</div>
</div>
<div class="card" style="padding: 20px;">
<div class="mb-3">
Who I want to be?
</div>
<div class="mb-3">
<div class="d-inline-flex align-items-center">
<PvAutoComplete inputStyle="width: 600px;" v-model="selectedUser" optionLabel="label" :suggestions="filteredUsers" @complete="searchUser" placeholder="Search user..." />
</div>
</div>
<div class="d-flex align-items-center justify-content-center">
<button type="button" class="btn btn-primary" @click="loginAs">Login as</button>
</div>
</div>
</div>
`
});
loginAsApp.
use(PluginsPhrasen).
use(primevue.config.default, {
zIndex: {
overlay: 1100
}
}).
mount('#main');
+59
View File
@@ -0,0 +1,59 @@
/**
* Copyright (C) 2025 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export default {
loginLDAP(params) {
return {
method: 'post',
url: '/api/frontend/v1/Login/loginLDAP',
params
};
},
loginASByUid(params) {
return {
method: 'post',
url: '/api/frontend/v1/Login/loginASByUid',
params
};
},
loginASByPersonId(params) {
return {
method: 'post',
url: '/api/frontend/v1/Login/loginASByPersonId',
params
};
},
whoAmI() {
return {
method: 'get',
url: '/api/frontend/v1/Login/whoAmI'
};
},
logout() {
return {
method: 'get',
url: '/system/Logout'
};
},
searchUser(query) {
return {
method: 'get',
url: '/api/frontend/v1/Login/searchUser?query=' + encodeURIComponent(query)
};
}
};
-7
View File
@@ -36,12 +36,5 @@ export default {
url: '/api/frontend/v1/searchbar/searchStv',
params
};
},
searchPV(params) {
return {
method: 'post',
url: '/api/frontend/v1/searchbar/searchPV',
params
};
}
};
@@ -27,7 +27,7 @@ export default {
return {
filter: false,
studiengang_kz: false,
counterdate: luxon.DateTime.now().setZone(FHC_JS_DATA_STORAGE_OBJECT.timezone).toISODate()
counterdate: new Date()
};
},
computed: {
@@ -259,7 +259,6 @@ export default {
<form-input
type="DatePicker"
v-model="counterdate"
model-type="yyyy-MM-dd"
input-group
:enable-time-picker="false"
text-input
@@ -79,7 +79,6 @@ export default {
<form-input
type="DatePicker"
v-model="data.buchungsdatum"
model-type="yyyy-MM-dd"
name="buchungsdatum"
:label="$p.t('konto/buchungsdatum')"
:enable-time-picker="false"
@@ -88,7 +88,7 @@ export default {
this.data = {
buchungstyp_kurzbz: '',
betrag: '-0.00',
buchungsdatum: luxon.DateTime.now().setZone(FHC_JS_DATA_STORAGE_OBJECT.timezone).toISODate(),
buchungsdatum: new Date(),
buchungstext: '',
mahnspanne: 30,
studiensemester_kurzbz: this.currentSemester,
@@ -154,7 +154,6 @@ export default {
<form-input
type="DatePicker"
v-model="data.buchungsdatum"
model-type="yyyy-MM-dd"
name="buchungsdatum"
:label="$p.t('konto/buchungsdatum')"
:enable-time-picker="false"
@@ -325,7 +325,6 @@ export default {
:label="$p.t('infocenter', 'zgvDatum')"
type="DatePicker"
v-model="data.zgvdatum"
model-type="yyyy-MM-dd"
name="zgvdatum"
no-today
auto-apply
@@ -390,7 +389,6 @@ export default {
:label="$p.t('lehre', 'zgvMasterDatum')"
type="DatePicker"
v-model="data.zgvmadatum"
model-type="yyyy-MM-dd"
name="zgvmadatum"
no-today
auto-apply
@@ -456,7 +454,6 @@ export default {
:label="$p.t('lehre', 'zgvDoktorDatum')"
type="DatePicker"
v-model="data.zgvdoktordatum"
model-type="yyyy-MM-dd"
name="zgvdoktordatum"
no-today
auto-apply
+8 -16
View File
@@ -218,23 +218,15 @@ export const CoreFilterCmpt = {
},
columnsForFilter() {
if (!this.filteredColumns || !this.datasetMetadata) return [];
const localizedColumnTitles = this.tabulator.getLang().columns;
const isTabulatorLocalized = !!this.$props.tabulatorOptions.locale;
let filterTitles;
if (isTabulatorLocalized) {
const localizedColumnTitles = this.tabulator.getLang().columns;
filterTitles = this.filteredColumns.reduce((a, c) => {
a[c.field] = localizedColumnTitles[c.field];
return a;
}, {});
} else {
filterTitles = this.filteredColumns.reduce((a, c) => {
a[c.field] = c.title;
return a;
}, {});
}
const filterTitles = this.filteredColumns.reduce((a, c) => {
a[c.field] =
isTabulatorLocalized && localizedColumnTitles[c.field]
? localizedColumnTitles[c.field]
: c.title;
return a;
}, {});
return this.datasetMetadata.map((el) => ({
...el,
...{ title: filterTitles[el.name] },
Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

-20
View File
@@ -55257,26 +55257,6 @@ and represent the current state of research on the topic. The prescribed citatio
)
)
),
array(
'app' => 'core',
'category' => 'search',
'phrase' => 'type_unassigned_employee',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Mitarbeiter ohne Zuordnung',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'unassigned employee',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'search',