aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/admin/login_style.php (renamed from app/controllers/admin/loginstyle.php)112
-rw-r--r--app/views/admin/login_style/edit_faq.php30
-rw-r--r--app/views/admin/login_style/index.php78
-rw-r--r--app/views/admin/login_style/login_faq.php57
-rw-r--r--app/views/admin/login_style/newpic.php5
-rw-r--r--app/views/new_password/index.php2
-rw-r--r--db/migrations/5.5.16_add_tooltip_fields_for_login.php71
-rw-r--r--db/migrations/5.5.17_add_login_faq_table.php29
-rw-r--r--db/migrations/5.5.18_add_login_faq_config.php53
-rw-r--r--lib/classes/auth_plugins/CASUserDataMapping.php3
-rw-r--r--lib/classes/auth_plugins/StudipAuthAbstract.class.php40
-rw-r--r--lib/classes/auth_plugins/StudipAuthLdap.class.php1
-rw-r--r--lib/classes/auth_plugins/StudipAuthStandard.class.php1
-rw-r--r--lib/models/LoginFaq.class.php32
-rw-r--r--lib/navigation/AdminNavigation.php13
-rw-r--r--lib/navigation/LoginNavigation.php19
-rw-r--r--lib/navigation/StartNavigation.php2
-rw-r--r--lib/phplib/Seminar_Auth.class.php28
-rw-r--r--lib/seminar_open.php7
-rw-r--r--locale/en/LC_MESSAGES/studip.po2
-rw-r--r--public/index.php44
-rw-r--r--resources/assets/javascripts/bootstrap/application.js65
-rw-r--r--resources/assets/stylesheets/scss/index.scss85
-rw-r--r--resources/assets/stylesheets/scss/responsive.scss7
-rw-r--r--resources/assets/stylesheets/scss/variables.scss3
-rw-r--r--templates/_standard_loginform.php76
-rw-r--r--templates/loginform.php167
-rw-r--r--tests/e2e/login.spec.ts2
28 files changed, 859 insertions, 175 deletions
diff --git a/app/controllers/admin/loginstyle.php b/app/controllers/admin/login_style.php
index f998b3a..615e777 100644
--- a/app/controllers/admin/loginstyle.php
+++ b/app/controllers/admin/login_style.php
@@ -11,6 +11,7 @@
class Admin_LoginStyleController extends AuthenticatedController
{
+ protected $_autobind = true;
/**
* common tasks for all actions
*
@@ -21,15 +22,24 @@ class Admin_LoginStyleController extends AuthenticatedController
{
parent::before_filter($action, $args);
- // user must have root permission
$GLOBALS['perm']->check('root');
//setting title and navigation
PageLayout::setTitle(_('Hintergrundbilder für den Startbildschirm'));
Navigation::activateItem('/admin/locations/loginstyle');
- // Setup sidebar
- $this->setSidebar();
+ $views = new ViewsWidget();
+ $views->addLink(
+ _('Bilder'),
+ $this->indexURL()
+ )->setActive($action === 'index');
+
+ $views->addLink(
+ _('Hinweise zum Login'),
+ $this->login_faqURL()
+ )->setActive($action === 'login_faq');
+
+ Sidebar::Get()->addWidget($views);
}
/**
@@ -37,6 +47,8 @@ class Admin_LoginStyleController extends AuthenticatedController
*/
public function index_action()
{
+ // Setup sidebar
+ $this->setSidebar('index');
$this->pictures = LoginBackground::findBySQL("1 ORDER BY `background_id`");
}
@@ -50,7 +62,7 @@ class Admin_LoginStyleController extends AuthenticatedController
/**
* Adds a new picture ass possible login background.
*/
- public function add_action()
+ public function add_pic_action()
{
CSRFProtection::verifyRequest();
$success = 0;
@@ -96,15 +108,16 @@ class Admin_LoginStyleController extends AuthenticatedController
$fail
), $fail));
}
- $this->relocate('admin/loginstyle');
+ $this->relocate($this->indexURL());
}
/**
* Deletes the given picture.
- * @param $id the picture to delete
+ * @param string $id the picture to delete
*/
- public function delete_action($id)
+ public function delete_pic_action($id)
{
+ CSRFProtection::verifyUnsafeRequest();
$pic = LoginBackground::find($id);
if ($pic->in_release) {
PageLayout::postError(_('Dieses Bild wird vom System mitgeliefert und kann daher nicht gelöscht werden.'));
@@ -114,17 +127,22 @@ class Admin_LoginStyleController extends AuthenticatedController
PageLayout::postError(_('Das Bild konnte nicht gelöscht werden.'));
}
- $this->relocate('admin/loginstyle');
+ $this->relocate($this->indexURL());
}
/**
* (De-)activate the given picture for given view.
- * @param $id the picture to change activation for
- * @param $view one of 'desktop', 'mobile', view to (de-) activate picture for
- * @param $newStatus new activation status for given view.
+ * @param string $id the picture to change activation for
+ * @param string $view one of 'desktop', 'mobile', view to (de-) activate picture for
+ * @param string $newStatus new activation status for given view.
*/
public function activation_action($id, $view, $newStatus)
{
+ CSRFProtection::verifyUnsafeRequest();
+ if (!in_array($view, ['desktop', 'mobile'])) {
+ throw new InvalidArgumentException('You may not change this attribute.');
+ }
+
$pic = LoginBackground::find($id);
$pic->$view = $newStatus;
if ($pic->store()) {
@@ -132,22 +150,74 @@ class Admin_LoginStyleController extends AuthenticatedController
} else {
PageLayout::postSuccess(_('Der Aktivierungsstatus konnte nicht gespeichert werden.'));
}
- $this->relocate('admin/loginstyle');
+ $this->relocate($this->indexURL());
}
+
/**
- * Adds the content to sidebar
+ * FAQ part of login page
*/
- protected function setSidebar()
+ public function login_faq_action()
{
- $sidebar = Sidebar::get();
+ PageLayout::setTitle(_('Hinweise zum Login für den Startbildschirm'));
+
+ $this->setSidebar('login_faq');
+ $this->faq_entries = LoginFaq::findBySql('1');
+ }
+
+ public function edit_faq_action(LoginFaq $entry = null)
+ {
+ PageLayout::setTitle(
+ $entry->isNew() ? _('Hinweistext hinzufügen') : _('Hinweistext bearbeiten')
+ );
+ }
+
+ public function store_faq_action(LoginFaq $entry = null)
+ {
+ CSRFProtection::verifyRequest();
+
+ $entry->setData([
+ 'title' => trim(Request::get('title')),
+ 'description' => trim(Request::get('description')),
+ ]);
+ if ($entry->store()) {
+ PageLayout::postSuccess(_('Hinweistext wurde gespeichert.'));
+ }
+
+ $this->relocate($this->login_faqURL());
+ }
+
+ public function delete_faq_action(LoginFaq $entry)
+ {
+ CSRFProtection::verifyRequest();
+
+ if ($entry->delete()) {
+ PageLayout::postSuccess(_('Der Hinweistext wurde gelöscht.'));
+ }
+
+ $this->relocate($this->login_faqURL());
+ }
+
+ /**
+ * Adds the content to sidebar
+ */
+ protected function setSidebar($action)
+ {
$links = new ActionsWidget();
- $links->addLink(
- _('Bild hinzufügen'),
- $this->url_for('admin/loginstyle/newpic'),
- Icon::create('add', 'clickable')
- )->asDialog('size=auto');
- $sidebar->addWidget($links);
+ if ($action === 'index') {
+ $links->addLink(
+ _('Bild hinzufügen'),
+ $this->newpicURL(),
+ Icon::create('add')
+ )->asDialog('size=auto');
+ } else if ($action === 'login_faq') {
+ $links->addLink(
+ _('Hinweistext hinzufügen'),
+ $this->edit_faqURL(),
+ Icon::create('add')
+ )->asDialog();
+ }
+ Sidebar::get()->addWidget($links);
}
}
diff --git a/app/views/admin/login_style/edit_faq.php b/app/views/admin/login_style/edit_faq.php
new file mode 100644
index 0000000..66020a0
--- /dev/null
+++ b/app/views/admin/login_style/edit_faq.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ * @var Admin_LoginStyleController $controller
+ * @var LoginFaq $entry
+ */
+?>
+<form action="<?= $controller->store_faq($entry) ?>"
+ method="post"
+ enctype="multipart/form-data"
+ class="default">
+ <?= CSRFProtection::tokenTag() ?>
+
+ <label class="studiprequired">
+ <?= _('Titel') ?>
+ <span title="<?= _('Dies ist ein Pflichtfeld') ?>" aria-hidden="true" class="asterisk">*</span>
+ <input type="text" name="title" value="<?= htmlReady($entry->title) ?>" required>
+ </label>
+
+ <label class="studiprequired">
+ <?= _('Text') ?>
+ <span title="<?= _('Dies ist ein Pflichtfeld') ?>" aria-hidden="true" class="asterisk">*</span>
+ <textarea name="description"
+ class="add_toolbar wysiwyg" data-editor="toolbar=minimal"><?= htmlReady($entry->description)?></textarea>
+ </label>
+
+ <div data-dialog-button>
+ <?= \Studip\Button::create(_('Speichern')) ?>
+ </div>
+
+</form>
diff --git a/app/views/admin/login_style/index.php b/app/views/admin/login_style/index.php
index 195cc6a..24c0b70 100644
--- a/app/views/admin/login_style/index.php
+++ b/app/views/admin/login_style/index.php
@@ -4,28 +4,31 @@
* @var Admin_LoginStyleController $controller
*/
?>
-<? if (count($pictures) > 0) : ?>
+<form method="post">
+ <?= CSRFProtection::tokenTag(); ?>
+
+ <? if (count($pictures) > 0) : ?>
<table class="default">
<caption>
<?= _('Hintergrundbilder für den Startbildschirm') ?>
</caption>
<colgroup>
<col>
- <col width="400">
- <col width="100">
- <col width="25">
+ <col style="width: 400px">
+ <col style="width: 100px">
+ <col style="width: 25px">
</colgroup>
<thead>
- <tr>
- <th><?= _('Info') ?></th>
- <th><?= _('Vorschau') ?></th>
- <th><?= _('Aktiviert für') ?></th>
- <th><?= _('Aktionen') ?></th>
- </tr>
+ <tr>
+ <th><?= _('Info') ?></th>
+ <th><?= _('Vorschau') ?></th>
+ <th><?= _('Aktiviert für') ?></th>
+ <th><?= _('Aktionen') ?></th>
+ </tr>
</thead>
<? foreach ($pictures as $pic) :
$dim = $pic->getDimensions();
- ?>
+ ?>
<tr>
<td>
<?= htmlReady($pic->filename) ?>
@@ -37,34 +40,41 @@
<img src="<?= $pic->getURL() ?>" width="400">
</td>
<td>
- <a href="<?= $controller->link_for("admin/loginstyle/activation/{$pic->id}/desktop", (int) !$pic->desktop) ?>">
- <?= Icon::create('computer', $pic->desktop ? Icon::ROLE_CLICKABLE : Icon::ROLE_INACTIVE)->asImg(32, [
- 'title' => $pic->desktop
- ? _('Bild nicht mehr für die Desktopansicht verwenden')
- : _('Bild für die Desktopansicht verwenden')
- ]) ?>
- </a>
- <a href="<?= $controller->link_for("admin/loginstyle/activation/{$pic->id}/mobile", (int) !$pic->mobile) ?>">
- <?= Icon::create('cellphone', $pic->mobile ? Icon::ROLE_CLICKABLE : Icon::ROLE_INACTIVE)->asImg(32, [
+ <?= Icon::create('computer', $pic->desktop ? Icon::ROLE_CLICKABLE : Icon::ROLE_INACTIVE)->asInput(
+ 32,
+ [
+ 'title' => $pic->mobile
+ ? _('Bild nicht mehr für die Mobilansicht verwenden')
+ : _('Bild für die Mobilansicht verwenden'),
+ 'formaction' => $controller->activationURL($pic->id, 'desktop', (int) !$pic->desktop)
+ ]
+ )?>
+
+ <?= Icon::create('cellphone', $pic->mobile ? Icon::ROLE_CLICKABLE : Icon::ROLE_INACTIVE)->asInput(
+ 32,
+ [
'title' => $pic->mobile
- ? _('Bild nicht mehr für die Mobilansicht verwenden')
- : _('Bild für die Mobilansicht verwenden')
- ]) ?>
- </a>
+ ? _('Bild nicht mehr für die Mobilansicht verwenden')
+ : _('Bild für die Mobilansicht verwenden'),
+ 'formaction' => $controller->activationURL($pic->id, 'mobile', (int) !$pic->mobile)
+ ]
+ )?>
</td>
<td class="actions">
- <? if (!$pic->in_release): ?>
- <a href="<?= $controller->link_for("admin/loginstyle/delete/{$pic->id}") ?>">
- <?= Icon::create('trash')->asImg([
- 'title' => _('Bild löschen'),
- 'data-confirm' => _('Soll das Bild wirklich gelöscht werden?'),
- ]) ?>
- </a>
- <? endif; ?>
+ <? if (!$pic->in_release): ?>
+ <?= Icon::create('trash')->asInput(
+ [
+ 'title' => _('Bild löschen'),
+ 'data-confirm' => _('Soll das Bild wirklich gelöscht werden?'),
+ 'formaction' => $controller->delete_picURL($pic->id)
+ ]
+ )?>
+ <? endif ?>
</td>
</tr>
<? endforeach ?>
</table>
-<? else : ?>
+ <? else : ?>
<?= MessageBox::info(_('In Ihrem System sind leider keine Bilder für den Startbildschirm hinterlegt.')) ?>
-<? endif ?>
+ <? endif ?>
+</form>
diff --git a/app/views/admin/login_style/login_faq.php b/app/views/admin/login_style/login_faq.php
new file mode 100644
index 0000000..4ed19e1
--- /dev/null
+++ b/app/views/admin/login_style/login_faq.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * @var Admin_LoginStyleController $controller
+ * @var LoginFaq[] $faq_entries
+ */
+?>
+<form method="post">
+ <?= CSRFProtection::tokenTag() ?>
+ <table class="default">
+ <caption><?= _('Hinweise zum Login') ?></caption>
+ <thead>
+ <tr>
+ <th><?= _('Titel') ?></th>
+ <th class="actions"><?= _('Aktionen') ?></th>
+ </tr>
+ </thead>
+ <tbody>
+ <? if (count($faq_entries) > 0) : ?>
+ <? foreach ($faq_entries as $entry) : ?>
+ <tr>
+ <td><?= htmlReady($entry->title) ?></td>
+ <td class="actions">
+ <?= ActionMenu::get()
+ ->setContext($entry->title)
+ ->addLink(
+ $controller->edit_faqURL($entry),
+ _('Hinweistext bearbeiten'),
+ Icon::create('edit'),
+ ['data-dialog' => 'size=medium']
+ )->addButton(
+ 'delete',
+ _('Hinweistext löschen'),
+ Icon::create('trash'),
+ [
+ 'formaction' => $controller->delete_faqURL($entry),
+ 'data-confirm' => sprintf(
+ _('Wollen Sie den Hinweistext "%s" wirklich löschen?'),
+ $entry->title
+ ),
+ 'data-dialog' => 'size=auto',
+ ]
+ )
+ ?>
+ </td>
+ </tr>
+ <? endforeach ?>
+ <? else : ?>
+ <tr>
+ <td colspan="3" style="text-align: center">
+ <?= _('Keine Hinweistexte vorhanden') ?>
+ </td>
+ </tr>
+ <? endif ?>
+ </tbody>
+
+ </table>
+</form>
diff --git a/app/views/admin/login_style/newpic.php b/app/views/admin/login_style/newpic.php
index d5bc74a..c5f7fbf 100644
--- a/app/views/admin/login_style/newpic.php
+++ b/app/views/admin/login_style/newpic.php
@@ -3,7 +3,8 @@
* @var Admin_LoginStyleController $controller
*/
?>
-<form class="default" action="<?= $controller->link_for('admin/loginstyle/add') ?>" method="post" enctype="multipart/form-data">
+<form class="default" action="<?= $controller->add_pic() ?>" method="post" enctype="multipart/form-data">
+ <?= CSRFProtection::tokenTag() ?>
<fieldset>
<legend>
<?= _('Bild(er) hinzufügen') ?>
@@ -33,6 +34,6 @@
<footer data-dialog-button>
<?= CSRFProtection::tokenTag() ?>
<?= Studip\Button::createAccept(_('Speichern'), 'store') ?>
- <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->url_for('loginstyle/index')) ?>
+ <?= Studip\LinkButton::createCancel(_('Abbrechen'), $controller->indexURL()) ?>
</footer>
</form>
diff --git a/app/views/new_password/index.php b/app/views/new_password/index.php
index 9cddc31..d044629 100644
--- a/app/views/new_password/index.php
+++ b/app/views/new_password/index.php
@@ -6,7 +6,7 @@
</legend>
<label>
- <?= _('Geben sie die Mail-Adresse des Zugangs an, für den sie das Passwort zurücksetzen möchten') ?>
+ <?= _('Geben Sie die Mail-Adresse des Zugangs an, für den Sie das Passwort zurücksetzen möchten') ?>
<input type="text" name="mail" placeholder="<?= _('Ihre Mail-Adresse') ?>" required>
</label>
</fieldset>
diff --git a/db/migrations/5.5.16_add_tooltip_fields_for_login.php b/db/migrations/5.5.16_add_tooltip_fields_for_login.php
new file mode 100644
index 0000000..f4d536b
--- /dev/null
+++ b/db/migrations/5.5.16_add_tooltip_fields_for_login.php
@@ -0,0 +1,71 @@
+<?php
+
+
+class AddTooltipFieldsForLogin extends Migration
+{
+ public function description()
+ {
+ return 'Creates config for login username and password tooltip texts';
+ }
+
+ public function up()
+ {
+ $query = 'INSERT INTO `config` (`field`, `value`, `type`, `section`, `range`, `description`, `mkdate`, `chdate`)
+ VALUES (:name, :value, :type, :section, :range, :description, UNIX_TIMESTAMP(), UNIX_TIMESTAMP())';
+ $statement = DBManager::get()->prepare($query);
+ $statement->execute([
+ 'name' => 'USERNAME_TOOLTIP_TEXT',
+ 'value' => 'Geben Sie hier Ihren Stud.IP-Benutzernamen ein.',
+ 'type' => 'i18n',
+ 'section' => 'Loginseite',
+ 'range' => 'global',
+ 'description' => 'Text für den Tooltip des Benutzernamens auf der Loginseite'
+ ]);
+
+ $statement->execute([
+ 'name' => 'PASSWORD_TOOLTIP_TEXT',
+ 'value' => 'Geben Sie hier Ihr Stud.IP-Passwort ein. Achten Sie bei der Eingabe auf Groß- und Kleinschreibung.',
+ 'type' => 'i18n',
+ 'section' => 'Loginseite',
+ 'range' => 'global',
+ 'description' => 'Text für den Tooltip des Benutzernamens auf der Loginseite'
+ ]);
+
+ $statement->execute([
+ 'name' => 'USERNAME_TOOLTIP_ACTIVATED',
+ 'value' => '1',
+ 'type' => 'boolean',
+ 'section' => 'Loginseite',
+ 'range' => 'global',
+ 'description' => 'Soll der Tooltip beim Benutzernamen auf der Loginseite sichtbar sein?'
+ ]);
+
+ $statement->execute([
+ 'name' => 'PASSWORD_TOOLTIP_ACTIVATED',
+ 'value' => '1',
+ 'type' => 'boolean',
+ 'section' => 'Loginseite',
+ 'range' => 'global',
+ 'description' => 'Soll der Tooltip beim Passwort auf der Loginseite sichtbar sein?'
+ ]);
+
+ }
+
+ public function down()
+ {
+ $query = "DELETE `config`, `config_values`, `i18n`
+ FROM `config`
+ LEFT JOIN `config_values` USING (`field`)
+ LEFT JOIN `i18n`
+ ON `table` = 'config'
+ AND `field` = 'value'
+ AND `object_id` = MD5(`config`.`field`)
+ WHERE `field` IN (
+ 'USERNAME_TOOLTIP_TEXT',
+ 'PASSWORD_TOOLTIP_TEXT',
+ 'USERNAME_TOOLTIP_ACTIVATED',
+ 'PASSWORD_TOOLTIP_ACTIVATED'
+ )";
+ DBManager::get()->exec($query);
+ }
+}
diff --git a/db/migrations/5.5.17_add_login_faq_table.php b/db/migrations/5.5.17_add_login_faq_table.php
new file mode 100644
index 0000000..2a99909
--- /dev/null
+++ b/db/migrations/5.5.17_add_login_faq_table.php
@@ -0,0 +1,29 @@
+<?php
+
+class AddLoginFaqTable extends Migration
+{
+ public function description()
+ {
+ return 'Create table for login page FAQ';
+ }
+
+ public function up()
+ {
+ $query = "CREATE TABLE IF NOT EXISTS `login_faq` (
+ `faq_id` int(11) NOT NULL AUTO_INCREMENT,
+ `title` varchar(255) NOT NULL,
+ `description` text NOT NULL,
+ PRIMARY KEY (`faq_id`)
+ )";
+ DBManager::get()->exec($query);
+ }
+
+ public function down()
+ {
+ DBManager::get()->exec('DROP TABLE IF EXISTS `login_faq`');
+
+ $query = "DELETE FROM `i18n`
+ WHERE `table` = 'login_faq`";
+ DBManager::get()->exec($query);
+ }
+}
diff --git a/db/migrations/5.5.18_add_login_faq_config.php b/db/migrations/5.5.18_add_login_faq_config.php
new file mode 100644
index 0000000..3196e34
--- /dev/null
+++ b/db/migrations/5.5.18_add_login_faq_config.php
@@ -0,0 +1,53 @@
+<?php
+
+
+class AddLoginFaqConfig extends Migration
+{
+ public function description()
+ {
+ return 'Creates configs for login faq: Visibility and title (eg.: Hilfe zum Login)';
+ }
+
+ public function up()
+ {
+ $query = 'INSERT INTO `config` (`field`, `value`, `type`, `section`, `range`, `description`, `mkdate`, `chdate`)
+ VALUES (:name, :value, :type, :section, :range, :description, UNIX_TIMESTAMP(), UNIX_TIMESTAMP())';
+ $statement = DBManager::get()->prepare($query);
+ $statement->execute([
+ 'name' => 'LOGIN_FAQ_TITLE',
+ 'value' => 'Hinweise zum Login',
+ 'type' => 'i18n',
+ 'section' => 'Loginseite',
+ 'range' => 'global',
+ 'description' => 'Überschrift für den FAQ-Bereich auf der Loginseite'
+ ]);
+
+ $statement->execute([
+ 'name' => 'LOGIN_FAQ_VISIBILITY',
+ 'value' => '1',
+ 'type' => 'boolean',
+ 'section' => 'Loginseite',
+ 'range' => 'global',
+ 'description' => 'Soll der FAQ-Bereich auf der Loginseite sichtbar sein?'
+ ]);
+
+ }
+
+ public function down()
+ {
+ $query = "DELETE `config`, `config_values`, `i18n`
+ FROM `config`
+ LEFT JOIN `config_values` USING (`field`)
+ LEFT JOIN `i18n`
+ ON `table` = 'config'
+ AND `field` = 'value'
+ AND `object_id` = MD5(`config`.`field`)
+ WHERE `field` IN (
+ 'LOGIN_FAQ_TITLE',
+ 'LOGIN_FAQ_VISIBILITY',
+ 'USERNAME_TOOLTIP_ACTIVATED',
+ 'PASSWORD_TOOLTIP_ACTIVATED'
+ )";
+ DBManager::get()->exec($query);
+ }
+}
diff --git a/lib/classes/auth_plugins/CASUserDataMapping.php b/lib/classes/auth_plugins/CASUserDataMapping.php
index 03c9cd2..166df55 100644
--- a/lib/classes/auth_plugins/CASUserDataMapping.php
+++ b/lib/classes/auth_plugins/CASUserDataMapping.php
@@ -1,4 +1,4 @@
-<?
+<?php
# Lifter007: TODO
# Lifter003: TODO
# Lifter010: TODO
@@ -10,4 +10,3 @@ interface CASUserDataMapping {
// reads one attribute identified by a key of a given user
function getUserData ($key, $username);
}
-?> \ No newline at end of file
diff --git a/lib/classes/auth_plugins/StudipAuthAbstract.class.php b/lib/classes/auth_plugins/StudipAuthAbstract.class.php
index d1bcfac..fd2d4e9 100644
--- a/lib/classes/auth_plugins/StudipAuthAbstract.class.php
+++ b/lib/classes/auth_plugins/StudipAuthAbstract.class.php
@@ -91,6 +91,14 @@ class StudipAuthAbstract
public $error_head;
/**
+ * toggles display of standard login
+ *
+ *
+ * @var bool $show_login
+ */
+ public $show_login;
+
+ /**
* @var $plugin_instances
*/
private static $plugin_instances;
@@ -121,6 +129,38 @@ class StudipAuthAbstract
}
/**
+ * static method to check if SSO login is enabled
+ *
+ * @return bool
+ */
+ public static function isSSOEnabled(): bool
+ {
+ self::getInstance();
+ foreach (self::$plugin_instances as $auth_plugin) {
+ if ($auth_plugin instanceof StudipAuthSSO) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * static method to check if standard login is enabled
+ *
+ * @return bool
+ */
+ public static function isLoginEnabled(): bool
+ {
+ self::getInstance();
+ foreach (self::$plugin_instances as $auth_plugin) {
+ if ($auth_plugin->show_login === true) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* static method to check authentication in all plugins
*
* if authentication fails in one plugin, the error message is stored and the next plugin is used
diff --git a/lib/classes/auth_plugins/StudipAuthLdap.class.php b/lib/classes/auth_plugins/StudipAuthLdap.class.php
index 5721cf4..7cb8686 100644
--- a/lib/classes/auth_plugins/StudipAuthLdap.class.php
+++ b/lib/classes/auth_plugins/StudipAuthLdap.class.php
@@ -40,6 +40,7 @@ class StudipAuthLdap extends StudipAuthAbstract
public $username_attribute = 'uid';
public $ldap_filter;
public $bad_char_regex = '/[^0-9_a-zA-Z]/';
+ public $show_login = true;
public $conn = null;
public $user_data = null;
diff --git a/lib/classes/auth_plugins/StudipAuthStandard.class.php b/lib/classes/auth_plugins/StudipAuthStandard.class.php
index 1a2c2ba..5bb3e65 100644
--- a/lib/classes/auth_plugins/StudipAuthStandard.class.php
+++ b/lib/classes/auth_plugins/StudipAuthStandard.class.php
@@ -37,6 +37,7 @@ class StudipAuthStandard extends StudipAuthAbstract
{
var $bad_char_regex = false;
+ public $show_login = true;
/**
*
diff --git a/lib/models/LoginFaq.class.php b/lib/models/LoginFaq.class.php
new file mode 100644
index 0000000..036f0f7
--- /dev/null
+++ b/lib/models/LoginFaq.class.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * LoginFaq.class.php
+ * model class for table login_faq
+ *
+ *
+ *
+ * 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 2 of
+ * the License, or (at your option) any later version.
+ *
+ * @author Michaela Brückner <brueckner@data-quest.de>
+ * @copyright 2023 data-quest
+ * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
+ * @category Stud.IP
+ * @since 5.5
+*/
+class LoginFaq extends SimpleORMap
+{
+ /**
+ * @param array $config
+ */
+ protected static function configure($config = [])
+ {
+ $config['db_table'] = 'login_faq';
+
+ $config['i18n'] = ['title', 'description'];
+
+ parent::configure($config);
+ }
+}
diff --git a/lib/navigation/AdminNavigation.php b/lib/navigation/AdminNavigation.php
index 12bf53a..7d9cd2d 100644
--- a/lib/navigation/AdminNavigation.php
+++ b/lib/navigation/AdminNavigation.php
@@ -110,7 +110,6 @@ class AdminNavigation extends Navigation
}
$navigation->addSubNavigation('sem_classes', new Navigation(_('Veranstaltungskategorien'), 'dispatch.php/admin/sem_classes/overview'));
- $navigation->addSubNavigation('loginstyle', new Navigation(_('Startbildschirm'), 'dispatch.php/admin/loginstyle'));
$navigation->addSubNavigation(
'content_terms_of_use',
new Navigation(
@@ -157,7 +156,6 @@ class AdminNavigation extends Navigation
'dispatch.php/admin/accessibility_info_text/index'
)
);
-
}
if ($GLOBALS['perm']->have_perm('admin')) {
@@ -165,6 +163,17 @@ class AdminNavigation extends Navigation
$navigation->addSubNavigation('stock_images', $pool);
}
+ if ($perm->have_perm('root')) {
+ $navigation->addSubNavigation(
+ 'loginstyle',
+ new Navigation(
+ _('Startseite'),
+ 'dispatch.php/admin/login_style'
+ )
+ );
+
+ }
+
$this->addSubNavigation('locations', $navigation);
// global config / user administration
diff --git a/lib/navigation/LoginNavigation.php b/lib/navigation/LoginNavigation.php
index db21236..96ec90e 100644
--- a/lib/navigation/LoginNavigation.php
+++ b/lib/navigation/LoginNavigation.php
@@ -23,13 +23,20 @@ class LoginNavigation extends Navigation
{
parent::initSubNavigation();
- $navigation = new Navigation(_('Login'), 'index.php?again=yes');
- $navigation->setDescription(_('für registrierte NutzerInnen'));
- $this->addSubNavigation('login', $navigation);
-
+ $standard_login_active = false;
foreach (StudipAuthAbstract::getInstance() as $auth_plugin) {
+ if ($auth_plugin->show_login && !$standard_login_active) {
+ $navigation = new Navigation(_('Login'), '');
+ $navigation->setDescription($auth_plugin->login_description ?: _('für registrierte Nutzende'));
+ $navigation->setLinkAttributes([
+ 'id' => 'toggle-login'
+ ]);
+ $navigation->setURL('#login-form');
+ $this->addSubNavigation('standard_login', $navigation);
+ $standard_login_active = true;
+ }
if ($auth_plugin instanceof StudipAuthSSO && isset($auth_plugin->login_description)) {
- $navigation = new Navigation($auth_plugin->plugin_fullname . ' ' . _('Login'), 'index.php?again=yes&sso=' . $auth_plugin->plugin_name);
+ $navigation = new Navigation($auth_plugin->plugin_fullname . ' ' . _('Login'), '?sso=' . $auth_plugin->plugin_name);
$navigation->setDescription($auth_plugin->login_description);
$this->addSubNavigation('login_' . $auth_plugin->plugin_name, $navigation);
}
@@ -37,7 +44,7 @@ class LoginNavigation extends Navigation
if (Config::get()->ENABLE_SELF_REGISTRATION) {
$navigation = new Navigation(_('Registrieren'), 'register1.php');
- $navigation->setDescription(_('um NutzerIn zu werden'));
+ $navigation->setDescription(_('um das System erstmalig zu nutzen'));
$this->addSubNavigation('register', $navigation);
}
diff --git a/lib/navigation/StartNavigation.php b/lib/navigation/StartNavigation.php
index 3d3719e..df94412 100644
--- a/lib/navigation/StartNavigation.php
+++ b/lib/navigation/StartNavigation.php
@@ -22,7 +22,7 @@ class StartNavigation extends Navigation
{
$url = (is_object($GLOBALS['user']) && $GLOBALS['user']->id != 'nobody')
? 'dispatch.php/start'
- : 'index.php';
+ : 'index.php?again=yes';
parent::__construct(_('Start'), $url);
}
diff --git a/lib/phplib/Seminar_Auth.class.php b/lib/phplib/Seminar_Auth.class.php
index 30a6d46..80f6cea 100644
--- a/lib/phplib/Seminar_Auth.class.php
+++ b/lib/phplib/Seminar_Auth.class.php
@@ -301,6 +301,27 @@ class Seminar_Auth
throw new AccessDeniedException();
}
+ // if desired, switch to high contrast stylesheet and store when user logs in
+ if (Request::get('unset_contrast')) {
+ unset($_SESSION['contrast']);
+ PageLayout::removeStylesheet('accessibility.css');
+
+ }
+ if (Request::get('set_contrast') ) {
+ $_SESSION['contrast'] = true;
+ PageLayout::addStylesheet('accessibility.css');
+
+ }
+
+ // evaluate language clicks
+ // has to be done before seminar_open to get switching back to german (no init of i18n at all))
+ if (Request::get('set_language')) {
+ if (array_key_exists(Request::get('set_language'), $GLOBALS['INSTALLED_LANGUAGES'])) {
+ $_SESSION['forced_language'] = Request::get('set_language');
+ $_SESSION['_language'] = Request::get('set_language');
+ }
+ }
+
$this->check_environment();
PageLayout::setBodyElementId('login');
@@ -322,6 +343,13 @@ class Seminar_Auth
$login_template->set_attribute('error_msg', $this->error_msg);
$login_template->set_attribute('uname', (isset($this->auth["uname"]) ? $this->auth["uname"] : Request::username('loginname')));
$login_template->set_attribute('self_registration_activated', Config::get()->ENABLE_SELF_REGISTRATION);
+
+ $query = "SHOW TABLES LIKE 'login_faq'";
+ $result = DBManager::get()->query($query);
+
+ if ($result && $result->rowCount() > 0) {
+ $login_template->set_attribute('faq_entries', LoginFaq::findBySQL("1"));
+ }
}
PageLayout::setHelpKeyword('Basis.AnmeldungLogin');
$header_template = $GLOBALS['template_factory']->open('header');
diff --git a/lib/seminar_open.php b/lib/seminar_open.php
index c3e15c3..0ca9991 100644
--- a/lib/seminar_open.php
+++ b/lib/seminar_open.php
@@ -105,6 +105,13 @@ if ($auth->is_authenticated() && is_object($user) && $user->id != "nobody") {
UserConfig::get($GLOBALS['user']->id)->store('USER_HIGH_CONTRAST', $_SESSION['contrast']);
unset($_SESSION['contrast']);
}
+ // store last language click
+ if (!empty($_SESSION['forced_language'])) {
+ User::findCurrent()->preferred_language = $_SESSION['forced_language'];
+ User::findCurrent()->store();
+ $_SESSION['_language'] = $_SESSION['forced_language'];
+ }
+ $_SESSION['forced_language'] = null;
$user_did_login = true;
}
diff --git a/locale/en/LC_MESSAGES/studip.po b/locale/en/LC_MESSAGES/studip.po
index 0ff799a..29266c9 100644
--- a/locale/en/LC_MESSAGES/studip.po
+++ b/locale/en/LC_MESSAGES/studip.po
@@ -41881,7 +41881,7 @@ msgid "Sie haben keine alten empfangenen Nachrichten"
msgstr "You do not have any old received messages"
#: lib/navigation/LoginNavigation.php:27
-msgid "für registrierte NutzerInnen"
+msgid "für registrierte Nutzende"
msgstr "for registered users"
#: lib/navigation/LoginNavigation.php:40
diff --git a/public/index.php b/public/index.php
index c32fe49..2a38355 100644
--- a/public/index.php
+++ b/public/index.php
@@ -59,51 +59,9 @@ if ($auth->is_authenticated() && $user->id != 'nobody') {
closeObject();
include 'lib/seminar_open.php'; // initialise Stud.IP-Session
+$auth->login_if($user->id === 'nobody');
// if new start page is in use, redirect there (if logged in)
if ($auth->is_authenticated() && $user->id != 'nobody') {
header('Location: ' . URLHelper::getURL('dispatch.php/start'));
- die;
}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * * L O G I N - P A G E ( N O B O D Y - U S E R ) * *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
-PageLayout::setHelpKeyword("Basis.Startseite"); // set keyword for new help
-PageLayout::setTitle(_("Startseite"));
-Navigation::activateItem('/start');
-PageLayout::setTabNavigation(NULL); // disable display of tabs
-
-// Start of Output
-include 'lib/include/html_head.inc.php'; // Output of html head
-include 'lib/include/header.php';
-
-// Prüfen, ob PortalPlugins vorhanden sind.
-// TODO: Remove for Stud.IP 6.0
-/** @deprecated */
-$portalplugins = PluginEngine::getPlugins('PortalPlugin');
-$layout = $GLOBALS['template_factory']->open('shared/index_box');
-
-$plugin_contents = [];
-foreach ($portalplugins as $portalplugin) {
- $template = $portalplugin->getPortalTemplate();
-
- if ($template) {
- $plugin_contents[] = $template->render(NULL, $layout);
- $layout->clear_attributes();
- }
-}
-
-
-$index_nobody_template = $GLOBALS['template_factory']->open('index_nobody');
-$index_nobody_template->set_attributes([
- 'plugin_contents' => $plugin_contents,
- 'logout' => Request::bool('logout'),
-]);
-
-echo $index_nobody_template->render();
-
-page_close();
-
-include 'lib/include/html_end.inc.php';
diff --git a/resources/assets/javascripts/bootstrap/application.js b/resources/assets/javascripts/bootstrap/application.js
index 1629b9b..830f2c0 100644
--- a/resources/assets/javascripts/bootstrap/application.js
+++ b/resources/assets/javascripts/bootstrap/application.js
@@ -355,3 +355,68 @@ jQuery(document).on('click', 'a[data-behaviour~="ajax-toggle"]', function (event
$('#open_variable').attr('value', $(this).parent('fieldset').data('open'));
});
}(jQuery));
+
+STUDIP.domReady(function () {
+ const loginForm = document.getElementById('login-form');
+ if (!loginForm) {
+ return;
+ }
+
+ const passwordInput = document.getElementById('password');
+ const usernameInput = document.getElementById('loginname');
+ const passwordCapsText = document.getElementById('password-caps');
+ const iconPasswordVisible = document.getElementById('visible-password');
+ const iconPasswordInVisible = document.getElementById('invisible-password');
+
+ [usernameInput, passwordInput].forEach((input) => {
+ input.addEventListener('keydown', (event) => {
+ if (event.getModifierState('CapsLock')) {
+ passwordCapsText.style.display = 'block';
+ } else {
+ passwordCapsText.style.display = 'none';
+ }
+ });
+ });
+
+ const toggleLogin = document.getElementById('toggle-login');
+ if (toggleLogin) {
+ loginForm.addEventListener('transitionend', (event) => {
+ if (event.propertyName !== 'max-height') {
+ return;
+ }
+
+ if (!loginForm.classList.contains('hide')) {
+ usernameInput.scrollIntoView({
+ behavior: 'smooth'
+ });
+ usernameInput.focus();
+ } else {
+ loginForm.setAttribute('hidden', '');
+ }
+ });
+
+ toggleLogin.addEventListener('click', (event) => {
+ if (loginForm.classList.contains('hide')) {
+ loginForm.removeAttribute('hidden');
+ }
+
+ setTimeout(() => {
+ loginForm.classList.toggle('hide');
+ }, 0);
+
+ event.preventDefault();
+ });
+ }
+
+ document.getElementById('password-toggle').addEventListener('click', () => {
+ if (passwordInput.type === 'password') {
+ passwordInput.type = 'text';
+ iconPasswordVisible.style.display = 'none';
+ iconPasswordInVisible.style.display = '';
+ } else {
+ passwordInput.type = 'password';
+ iconPasswordVisible.style.display = '';
+ iconPasswordInVisible.style.display = 'none';
+ }
+ });
+});
diff --git a/resources/assets/stylesheets/scss/index.scss b/resources/assets/stylesheets/scss/index.scss
index 2ecda5c..e9234de 100644
--- a/resources/assets/stylesheets/scss/index.scss
+++ b/resources/assets/stylesheets/scss/index.scss
@@ -13,6 +13,16 @@ $gap-between-boxes: calc($login-page-margin / 2);
#content {
grid-column: 1 / 3;
grid-row: 2 / 2;
+
+ &.loginpage {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ column-gap: 20px;
+ row-gap: 20px;
+ align-items: flex-start;
+ flex-basis: 450px;
+ }
}
#background-desktop {
@@ -36,14 +46,24 @@ $gap-between-boxes: calc($login-page-margin / 2);
}
}
+#login_flex {
+ display: flex;
+ flex-direction: row;
+ column-gap: 20px;
+ flex-wrap: wrap;
+ row-gap: 20px;
+ align-items: flex-start;
+}
+
#loginbox {
- background-color: rgba(255, 255, 255, 0.8);
- box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.5);
+ background-color: var(--white);
+ box-shadow: 0 0 8px rgba(0, 0, 0, 0.5);
padding: 20px;
width: 450px;
+ float: left;
header {
- margin: 10px 0 0 10px;
+ margin: 0 0 0 0;
h1 {
border-bottom: 0;
@@ -56,7 +76,7 @@ $gap-between-boxes: calc($login-page-margin / 2);
list-style-type: none;
margin: 0;
width: 450px;
- padding: 0 10px;
+ padding-inline-start: 0;
.login_link {
display: inline-block;
@@ -93,6 +113,10 @@ $gap-between-boxes: calc($login-page-margin / 2);
}
}
+ #contrast {
+ padding-bottom: 0;
+ }
+
div.login_info {
border-top: 1px solid var(--light-gray-color);
font-size: 0.8em;
@@ -110,6 +134,38 @@ $gap-between-boxes: calc($login-page-margin / 2);
margin-left: 12px;
}
}
+
+
+ input#loginname,
+ input#password {
+ display: initial;
+ }
+
+ input#password {
+ padding-right: 28px;
+ }
+
+ #password-toggle {
+ position: absolute;
+ right: 7px;
+ bottom: 0;
+ cursor: pointer;
+
+ #visible-password,
+ #invisible-password {
+ }
+ }
+}
+
+#faq_box {
+ background-color: var(--white);
+ box-shadow: 0 0 8px rgba(0, 0, 0, 0.5);
+ padding: 20px;
+ width: 450px;
+ float: left;
+ > header {
+ margin: 0 0 0 0;
+ }
}
#login-plugin-contents {
@@ -128,3 +184,24 @@ $gap-between-boxes: calc($login-page-margin / 2);
width: 418px;
}
}
+
+::-ms-reveal {
+ display: none;
+}
+
+
+#login-form {
+ max-height: 300px;
+ overflow: hidden;
+ transition: max-height var(--transition-duration-slow) linear;
+
+ &.hide {
+ max-height: 0px;
+ }
+
+ #submit_login {
+ margin-top: 0 !important;
+ float: left !important;
+
+ }
+}
diff --git a/resources/assets/stylesheets/scss/responsive.scss b/resources/assets/stylesheets/scss/responsive.scss
index a1f2a67..01c7403 100644
--- a/resources/assets/stylesheets/scss/responsive.scss
+++ b/resources/assets/stylesheets/scss/responsive.scss
@@ -897,7 +897,8 @@ html:not(.responsive-display):not(.fullscreen-mode) {
left: 0;
}
- #loginbox {
+ #loginbox,
+ #faq_box {
box-shadow: unset;
margin: 0;
width: calc(100vw - 40px);
@@ -912,6 +913,10 @@ html:not(.responsive-display):not(.fullscreen-mode) {
}
}
}
+
+ #faq_box {
+ margin: -20px 0 0 0;
+ }
}
}
diff --git a/resources/assets/stylesheets/scss/variables.scss b/resources/assets/stylesheets/scss/variables.scss
index ef5329e..a915e76 100644
--- a/resources/assets/stylesheets/scss/variables.scss
+++ b/resources/assets/stylesheets/scss/variables.scss
@@ -43,6 +43,7 @@ $drag_and_drop_z_index: 1000;
$drag_and_drop_border: 1px solid $base-color;
$transition-duration: .3s;
+$transition-duration-slow: .5s;
// Layout
$page-margin: 15px;
@@ -171,8 +172,10 @@ $grid-gap: 0;
#{"--"}group-color-8: $brown;
#{"--"}transition-duration: $transition-duration;
+ #{"--"}transition-duration-slow: $transition-duration-slow;
@media (prefers-reduced-motion) {
#{"--"}transition-duration: 0s;
+ #{"--"}transition-duration-slow: 0s;
}
}
diff --git a/templates/_standard_loginform.php b/templates/_standard_loginform.php
new file mode 100644
index 0000000..0a8be59
--- /dev/null
+++ b/templates/_standard_loginform.php
@@ -0,0 +1,76 @@
+<?php
+
+use Studip\Button;
+
+/**
+ * @var bool $hidden
+ * @var string $uname;
+ */
+?>
+
+<form class="default <?= $hidden ? 'hide' : '' ?>"
+ name="login_form"
+ id="login-form"
+ method="post"
+ action="<?= URLHelper::getLink(Request::url(), ['cancel_login' => null]) ?>"
+ <? if ($hidden) echo 'hidden'; ?>
+>
+ <section>
+ <label>
+ <span class="required"><?= _('Benutzername') ?></span>
+ <? if (Config::get()->USERNAME_TOOLTIP_ACTIVATED) : ?>
+ <?= tooltipIcon(htmlReady((string)Config::get()->USERNAME_TOOLTIP_TEXT)) ?>
+ <? endif ?>
+ <input type="text" <?= (mb_strlen($uname) || $hidden) ? '' : 'autofocus' ?>
+ id="loginname"
+ name="loginname"
+ value="<?= htmlReady($uname) ?>"
+ size="20"
+ spellcheck="false"
+ autocapitalize="off"
+ title="<?= _('Der Benutzername entspricht nicht den Anforderungen') ?>"
+ required>
+ </label>
+ <label for="password" style="position: relative">
+ <span class="required"><?= _('Passwort') ?></span>
+ <? if (Config::get()->PASSWORD_TOOLTIP_ACTIVATED) : ?>
+ <?= tooltipIcon(htmlReady((string)Config::get()->PASSWORD_TOOLTIP_TEXT)) ?>
+ <? endif ?>
+ <input type="password" <?= mb_strlen($uname) && !$hidden ? 'autofocus' : '' ?>
+ id="password"
+ name="password"
+ size="20"
+ required>
+
+ <i id="password-toggle" tabindex="0" aria-role="button" class="enter-accessible">
+ <?= Icon::create('visibility-checked')->asImg(20, [
+ 'id ' => 'visible-password',
+ 'title' => _('Passwort anzeigen'),
+ ]) ?>
+ <?= Icon::create('visibility-invisible')->asImg(20, [
+ 'id' => 'invisible-password',
+ 'style' => 'display: none',
+ 'title' => _('Passwort verstecken'),
+ ]) ?>
+ </i>
+
+ </label>
+ <p id="password-caps" style="display: none"><?= _('Feststelltaste ist aktiviert!') ?></p>
+ </section>
+
+ <?= CSRFProtection::tokenTag() ?>
+ <input type="hidden" name="login_ticket" value="<?= Seminar_Session::get_ticket() ?>">
+ <input type="hidden" name="resolution" value="">
+
+ <div style="display: flex; align-items: flex-start; justify-content: space-between; height: 70px;">
+ <?= Button::createAccept(_('Anmelden'), _('Login'), ['id' => 'submit_login']); ?>
+
+ <? if (Config::get()->ENABLE_REQUEST_NEW_PASSWORD_BY_USER && in_array('Standard', $GLOBALS['STUDIP_AUTH_PLUGIN'])): ?>
+ <a style="line-height: 1 !important" href="<?= URLHelper::getLink('dispatch.php/new_password?cancel_login=1') ?>">
+ <? else: ?>
+ <a style="line-height: 1 !important" href="mailto:<?= $GLOBALS['UNI_CONTACT'] ?>?subject=<?= rawurlencode('Stud.IP Passwort vergessen - '.Config::get()->UNI_NAME_CLEAN) ?>&amp;body=<?= rawurlencode('Ich habe mein Passwort vergessen. Bitte senden Sie mir ein Neues.\nMein Nutzername: ' . htmlReady($uname) . "\n") ?>">
+ <? endif; ?>
+ <?= _('Passwort vergessen?') ?>
+ </a>
+ </div>
+</form>
diff --git a/templates/loginform.php b/templates/loginform.php
index 348ccee..deb9768 100644
--- a/templates/loginform.php
+++ b/templates/loginform.php
@@ -1,6 +1,8 @@
<?php
-# Lifter010: TODO
-use Studip\Button, Studip\LinkButton;
+/**
+ * @var array $loginerror
+ * @var string $error_msg
+ */
// Get background images (this should be resolved differently since mobile
// browsers might still download the desktop background)
@@ -21,70 +23,122 @@ if (!match_route('web_migrate.php')) {
$bg_desktop = URLHelper::getURL('pictures/loginbackgrounds/1.jpg');
$bg_mobile = URLHelper::getURL('pictures/loginbackgrounds/2.jpg');
}
+$show_hidden_login = false;
?>
-<main id="content">
+<main id="content" class="loginpage">
<div id="background-desktop" style="background: url(<?= $bg_desktop ?>) no-repeat top left/cover;"></div>
<div id="background-mobile" style="background: url(<?= $bg_mobile ?>) no-repeat top left/cover;"></div>
- <? if ($loginerror): ?>
- <!-- failed login code -->
- <?= MessageBox::error(_('Bei der Anmeldung trat ein Fehler auf!'), [
- $error_msg,
- sprintf(
- _('Bitte wenden Sie sich bei Problemen an: <a href="mailto:%1$s">%1$s</a>'),
- $GLOBALS['UNI_CONTACT']
- )
- ]) ?>
- <? endif; ?>
- <?= implode('', PageLayout::getMessages()); ?>
+ <div id="login_flex">
+ <? if ($loginerror): ?>
+ <!-- failed login code -->
+ <?= MessageBox::error(_('Bei der Anmeldung trat ein Fehler auf!'), [
+ $error_msg,
+ sprintf(
+ _('Bitte wenden Sie sich bei Problemen an: <a href="mailto:%1$s">%1$s</a>'),
+ $GLOBALS['UNI_CONTACT']
+ )
+ ]) ?>
+ <? endif ?>
- <div id="loginbox">
- <form class="default" name="login" method="post" action="<?= URLHelper::getLink(Request::url(), ['cancel_login' => NULL]) ?>">
+ <?= implode('', PageLayout::getMessages()); ?>
+
+ <div id="loginbox">
<header>
- <h1 style="margin: 0; padding-bottom:10px;">
- <?=_('Herzlich willkommen!')?>
- </h1>
+ <h1><?= htmlReady(Config::get()->UNI_NAME_CLEAN) ?></h1>
</header>
- <section>
- <label>
- <?= _('Benutzername:') ?>
- <input type="text" <?= mb_strlen($uname) ? '' : 'autofocus' ?>
- id="loginname" name="loginname"
- value="<?= htmlReady($uname) ?>"
- size="20"
- autocorrect="off" autocapitalize="off">
- </label>
- </section>
- <section>
- <label for="password">
- <?= _('Passwort:') ?>
- <input type="password" <?= mb_strlen($uname) ? 'autofocus' : '' ?>
- id="password" name="password" size="20">
- </label>
- </section>
- <?= CSRFProtection::tokenTag() ?>
- <input type="hidden" name="login_ticket" value="<?=Seminar_Session::get_ticket();?>">
- <input type="hidden" name="resolution" value="">
- <?= Button::createAccept(_('Anmelden'), _('Login')); ?>
- <?= LinkButton::create(_('Abbrechen'), URLHelper::getURL('index.php', ['cancel_login' => 1], true)) ?>
- </form>
- <div>
- <? if (Config::get()->ENABLE_REQUEST_NEW_PASSWORD_BY_USER && in_array('Standard', $GLOBALS['STUDIP_AUTH_PLUGIN'])): ?>
- <a href="<?= URLHelper::getLink('dispatch.php/new_password?cancel_login=1') ?>">
- <? else: ?>
- <a href="mailto:<?= $GLOBALS['UNI_CONTACT'] ?>?subject=<?= rawurlencode('Stud.IP Passwort vergessen - '.Config::get()->UNI_NAME_CLEAN) ?>&amp;body=<?= rawurlencode('Ich habe mein Passwort vergessen. Bitte senden Sie mir ein Neues.\nMein Nutzername: ' . htmlReady($uname) . "\n") ?>">
- <? endif; ?>
- <?= _('Passwort vergessen') ?>
- </a>
- <? if ($self_registration_activated): ?>
- /
- <a href="<?= URLHelper::getLink('register1.php?cancel_login=1') ?>">
- <?= _('Registrieren') ?>
- </a>
- <? endif; ?>
+ <? if (count($GLOBALS['STUDIP_AUTH_PLUGIN']) === 1 && StudipAuthAbstract::isLoginEnabled()) : ?>
+ <?= $this->render_partial('_standard_loginform', [
+ 'hidden' => false,
+ ]) ?>
+ <? endif ?>
+ <nav>
+ <ul>
+ <? foreach (Navigation::getItem('/login') as $key => $nav) : ?>
+ <? if ($nav->isVisible()) : ?>
+ <? if ($key === 'standard_login') {
+ if (count($GLOBALS['STUDIP_AUTH_PLUGIN']) === 1 && StudipAuthAbstract::isLoginEnabled()) {
+ continue;
+ } else {
+ $show_hidden_login = true;
+ }
+ }
+ ?>
+ <? $name_and_title = explode(' - ', $nav->getTitle()) ?>
+ <li class="login_link">
+ <? if (is_internal_url($url = $nav->getURL())) : ?>
+ <? SkipLinks::addLink($name_and_title[0], $url) ?>
+ <a href="<?= URLHelper::getLink($url, ['cancel_login' => 1]) ?>" id="<?= $nav->getLinkAttributes()['id'] ?>">
+ <? else : ?>
+ <a href="<?= htmlReady($url) ?>" target="_blank" rel="noopener noreferrer">
+ <? endif ?>
+ <?= htmlReady($name_and_title[0]) ?>
+ <p>
+ <?= htmlReady(!empty($name_and_title[1]) ? $name_and_title[1] : $nav->getDescription()) ?>
+ </p>
+ </a>
+ </li>
+ <? endif ?>
+ <? endforeach ?>
+ </ul>
+ </nav>
+
+ <? if ($show_hidden_login) : ?>
+ <?= $this->render_partial('_standard_loginform', [
+ 'hidden' => empty($loginerror),
+ ]) ?>
+ <? endif ?>
+
+ <footer>
+ <? if ($GLOBALS['UNI_LOGIN_ADD']) : ?>
+ <div class="uni_login_add">
+ <?= $GLOBALS['UNI_LOGIN_ADD'] ?>
+ </div>
+ <? endif ?>
+
+ <div id="languages">
+ <? foreach ($GLOBALS['INSTALLED_LANGUAGES'] as $temp_language_key => $temp_language): ?>
+ <?= Assets::img('languages/' . $temp_language['picture'], ['alt' => $temp_language['name'], 'size' => '24']) ?>
+ <a href="<?= URLHelper::getLink('index.php', ['set_language' =>$temp_language_key ]) ?>">
+ <?= htmlReady($temp_language['name']) ?>
+ </a>
+ <? endforeach ?>
+ </div>
+
+ <div id="contrast">
+ <? if (isset($_SESSION['contrast'])) : ?>
+ <?= Icon::create('accessibility')->asImg(24) ?>
+ <a href="<?= URLHelper::getLink('index.php', ['unset_contrast' => 1, 'cancel_login' => 1]) ?>"><?= _('Normalen Kontrast aktivieren') ?></a>
+ <?= tooltipIcon(_('Aktiviert standardmäßige, nicht barrierefreie Kontraste.')); ?>
+ <? else : ?>
+ <?= Icon::create('accessibility')->asImg(24) ?>
+ <a href="<?= URLHelper::getLink('index.php', ['set_contrast' => 1, 'cancel_login' => 1]) ?>" id="highcontrastlink"><?= _('Hohen Kontrast aktivieren')?></a>
+ <?= tooltipIcon(_('Aktiviert einen hohen Kontrast gemäß WCAG 2.1. Diese Einstellung wird nach dem Login übernommen.'
+ . 'Sie können sie in Ihren persönlichen Einstellungen ändern.')); ?>
+ <? endif ?>
+ </div>
+
+ </footer>
</div>
+ <? if (Config::get()->LOGIN_FAQ_VISIBILITY && count($faq_entries) > 0) : ?>
+ <div id="faq_box">
+ <header><h1><?= htmlReady(Config::get()->LOGIN_FAQ_TITLE) ?></h1></header>
+ <? foreach ($faq_entries as $entry) : ?>
+ <article class="studip toggle">
+ <header>
+ <h1><a href="#"><?= htmlReady($entry->title) ?></a></h1>
+ </header>
+ <section><?= formatReady($entry->description) ?>
+ </section>
+ </article>
+ <? endforeach ?>
+ </div>
+ <? endif ?>
+
</div>
+
+
</main>
<script type="text/javascript" language="javascript">
@@ -92,6 +146,7 @@ if (!match_route('web_migrate.php')) {
$(function () {
$('form[name=login]').submit(function () {
$('input[name=resolution]', this).val( screen.width + 'x' + screen.height );
+ $('input[name=device_pixel_ratio]').val(window.devicePixelRatio || 1);
});
});
// -->
diff --git a/tests/e2e/login.spec.ts b/tests/e2e/login.spec.ts
index 95e44a6..2e859dd 100644
--- a/tests/e2e/login.spec.ts
+++ b/tests/e2e/login.spec.ts
@@ -8,7 +8,7 @@ test.describe('Loggin In - HTML Web Form @auth', () => {
await expect(page.locator('#loginbox')).toBeVisible();
- const loginLink = page.getByRole('link', { name: 'Login für registrierte NutzerInnen' });
+ const loginLink = page.getByRole('link', { name: 'Login für registrierte Nutzende' });
await expect(loginLink).toBeVisible();
await loginLink.click();