' . $text . '
'; 25 | } 26 | 27 | public static function cut(string $text, int $size = 15, string $t = ' (...) '): string 28 | { 29 | $s = strlen($text); 30 | if ($s > $size) { 31 | $start = (int) ($size / 2); 32 | return substr($text, 0, $start) . $t . substr($text, -$start); 33 | } 34 | return $text; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /plugins/media_auth/pages/index.php: -------------------------------------------------------------------------------- 1 | i18n('title')); // $this->i18n('title') ist eine Kurzform für rex_i18n::msg('dummy_title') 9 | 10 | // Die Subpages werden nicht mehr über den "subpage"-Parameter gesteuert, sondern mit über "page" (getrennt mit einem Slash, z. B. page=dummy/config) 11 | // Die einzelnen Teile des page-Pfades können mit der folgenden Funktion ausgelesen werden. 12 | // $subpage = rex_be_controller::getCurrentPagePart(2); 13 | 14 | // Subpages können über diese Methode eingebunden werden. So ist sichergestellt, dass auch Subpages funktionieren, 15 | // die von anderen Addons/Plugins hinzugefügt wurden 16 | 17 | $currentPage = rex_be_controller::getCurrentPageObject(); 18 | if (null !== $currentPage) { 19 | include $currentPage->getSubPath(); 20 | } 21 | -------------------------------------------------------------------------------- /plugins/auth/lib/yform/value/ycom_auth_load_user.php: -------------------------------------------------------------------------------- 1 | params['send']) { 8 | $fields = $this->getElement(2); 9 | if ('' != $fields) { 10 | $fields = explode(',', $this->getElement(2)); 11 | } else { 12 | $fields = []; 13 | } 14 | foreach ($this->params['values'] as $o) { 15 | if ((0 == count($fields) || in_array($o->getName(), $fields)) && $o->getName() != $this->getName()) { 16 | $o->setValue(@rex_ycom_auth::getUser()->getValue($o->getName())); 17 | } 18 | } 19 | } 20 | } 21 | 22 | public function getDescription(): string 23 | { 24 | return 'ycom_auth_load_user -> Beispiel: ycom_auth_load_user|label|opt:field1,field2,field3'; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /plugins/auth/lib/yform/validate/ycom_auth_password.php: -------------------------------------------------------------------------------- 1 | getValueObject(); 8 | 9 | $user = rex_ycom_auth::getUser(); 10 | if (null === $user) { 11 | // no user available -> error 12 | $this->params['warning'][$Object->getId()] = $this->params['error_class']; 13 | $this->params['warning_messages'][$Object->getId()] = $this->getElement(3); 14 | return; 15 | } 16 | 17 | $status = rex_ycom_auth::checkPassword($Object->getValue(), $user->getId()); 18 | if (!$status) { 19 | // password wrong 20 | $this->params['warning'][$Object->getId()] = $this->params['error_class']; 21 | $this->params['warning_messages'][$Object->getId()] = $this->getElement(3); 22 | } 23 | } 24 | 25 | public function getDescription(): string 26 | { 27 | return 'ycom_auth_password -> validate|ycom_auth_password|pswfield|warning_message'; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 REDAXO, www.redaxo.org 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /install.php: -------------------------------------------------------------------------------- 1 | delete 21 | $pluginDocs = __DIR__ . '/plugins/docs'; 22 | if (file_exists($pluginDocs)) { 23 | rex_dir::delete($pluginDocs); 24 | } 25 | 26 | foreach ($this->getInstalledPlugins() as $plugin) { 27 | // use path relative to __DIR__ to get correct path in update temp dir 28 | $file = __DIR__ . '/plugins/' . $plugin->getName() . '/install.php'; 29 | 30 | if (file_exists($file)) { 31 | $plugin->includeFile($file); 32 | } 33 | } 34 | 35 | // rex_yform_manager_table_api::generateTablesAndFields(); 36 | 37 | rex_delete_cache(); 38 | -------------------------------------------------------------------------------- /uninstall.php: -------------------------------------------------------------------------------- 1 | setQuery('DELETE FROM `' . rex::getTable('yform_table') . '` WHERE table_name = "' . rex::getTable('ycom_user') . '"'); 10 | $sql->setQuery('DELETE FROM `' . rex::getTable('yform_field') . '` WHERE table_name = "' . rex::getTable('ycom_user') . '"'); 11 | $sql->setQuery('DELETE FROM `' . rex::getTable('yform_history') . '` WHERE table_name = "' . rex::getTable('ycom_user') . '"'); 12 | 13 | rex_sql_table::get(rex::getTable('article')) 14 | ->removeColumn('ycom_auth_type') 15 | ->removeColumn('ycom_group_type') 16 | ->removeColumn('ycom_groups') 17 | ->alter(); 18 | 19 | rex_sql_table::get(rex::getTable('ycom_user_session')) 20 | ->drop(); 21 | 22 | rex_sql_table::get(rex::getTable('ycom_user')) 23 | ->drop(); 24 | 25 | foreach ($this->getInstalledPlugins() as $plugin) { 26 | // use path relative to __DIR__ to get correct path in update temp dir 27 | $file = __DIR__ . '/plugins/' . $plugin->getName() . '/uninstall.php'; 28 | 29 | if (file_exists($file)) { 30 | $plugin->includeFile($file); 31 | } 32 | } 33 | 34 | rex_yform_manager_table::deleteCache(); 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | YCom für REDAXO 5.15+ 2 | ============= 3 | 4 | YCom ist ein Addon, das REDAXO um eine Frontend-Authentifizierung erweitert. Dadurch lässt sich bspw. ein einfaches Login im Frontend umsetzen - ebenso wie eine komplexe Community-Verwaltung. 5 | 6 | Features 7 | -------- 8 | 9 | * Benutzerverwaltung: Erstellung und Verwaltung von Frontend-Benutzern 10 | * Selbständige Registierung: Nutzer können sich selbständig für einen geschützten Bereich registrieren 11 | * Passwort zurücksetzen: Frontend-Nutzer können selbständig ihr Passwort zurücksetzen 12 | * Gruppen-Berechtigungen: Frontend-Nutzer können bestimmten Gruppen zugeordnet und verwaltet werden 13 | * Sichtbarkeit: Die Sichtbarkeit von Artikeln und Kategorien kann für bestimmte Frontend-Nutzer aktiviert oder deaktiviert werden 14 | * Einstellungen: Je nach in den Einstellungen gewählten Artikel wird man beim Login/Logout auf einen bestimmten Artikel weitergeleitet. 15 | * Geschützter Zugriff auf Medien 16 | 17 | > Hinweis: Die einzelnen Features können losgelöst voneinander verwendet werden. 18 | 19 |  20 | 21 | Installation 22 | ------------ 23 | 24 | * Ins Backend einloggen und mit dem Installer installieren. 25 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yakamara/ycom", 3 | "require": { 4 | "onelogin/php-saml": "^3", 5 | "apereo/phpcas": "^1", 6 | "league/oauth2-client": "^2", 7 | "spomky-labs/otphp": "^11.0" 8 | }, 9 | "replace": { 10 | "psr/container": "*", 11 | "psr/http-message": "*", 12 | "psr/log": "*", 13 | "symfony/console": "*", 14 | "symfony/deprecation-contracts": "*", 15 | "symfony/http-foundation": "*", 16 | "symfony/polyfill-ctype": "*", 17 | "symfony/polyfill-php80": "*", 18 | "symfony/polyfill-php81": "*", 19 | "symfony/polyfill-php83": "*", 20 | "symfony/service-contracts": "*", 21 | "symfony/string": "*", 22 | "symfony/yaml": "*" 23 | }, 24 | "require-dev": { 25 | "redaxo/php-cs-fixer-config": "^2.0", 26 | "friendsofphp/php-cs-fixer": "^3.14", 27 | "phpunit/phpunit": "^9.5" 28 | }, 29 | "config": { 30 | "platform": { 31 | "php": "8.1.13" 32 | } 33 | }, 34 | "scripts": { 35 | "cs-dry": "php-cs-fixer fix -v --ansi --dry-run --config=.php-cs-fixer.dist.php", 36 | "cs-fix": "php-cs-fixer fix -v --ansi --config=.php-cs-fixer.dist.php", 37 | "unit-test": "phpunit --testdox" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /.github/workflows/code-style.yml: -------------------------------------------------------------------------------- 1 | name: PHP-CS-Fixer 2 | 3 | on: 4 | push: 5 | branches: [ master, main ] 6 | pull_request: 7 | branches: [ master, main ] 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | code-style: 14 | 15 | runs-on: ubuntu-latest 16 | permissions: 17 | contents: write # for Git to git apply 18 | 19 | steps: 20 | - uses: actions/checkout@v3 21 | 22 | - name: Setup PHP 23 | uses: shivammathur/setup-php@v2 24 | with: 25 | php-version: '8.1' 26 | extensions: gd, intl, pdo_mysql 27 | coverage: none # disable xdebug, pcov 28 | 29 | # install dependencies from composer.json 30 | - name: Install test dependencies 31 | env: 32 | COMPOSER: composer.json 33 | run: COMPOSER=.tools/composer-code-style.json composer install --prefer-dist --no-progress 34 | 35 | # run php-cs-fixer 36 | - name: Run PHP CS Fixer 37 | run: composer cs-dry 38 | 39 | # commit and push fixed files 40 | # - uses: stefanzweifel/git-auto-commit-action@v4 41 | # with: 42 | # commit_message: Apply php-cs-fixer changes 43 | -------------------------------------------------------------------------------- /plugins/auth/lib/yform/value/ycom_auth_logout.php: -------------------------------------------------------------------------------- 1 | getElement(3); 19 | $returnTos[] = rex_getUrl(rex_ycom_config::get('article_id_jump_logout')); 20 | 21 | $allowedDomains = ('' != $this->getElement(2)) ? explode(',', $this->getElement(2)) : []; 22 | $returnTo = rex_ycom_auth::getReturnTo($returnTos, $allowedDomains); 23 | 24 | rex_ycom_auth::logout($me); 25 | 26 | if ('' != $returnTo) { 27 | rex_response::sendCacheControl(); 28 | rex_response::sendRedirect($returnTo); 29 | } 30 | } 31 | } 32 | 33 | public function getDescription(): string 34 | { 35 | return 'ycom_auth_logout -> Beispiel: ycom_auth_logout|label|[allowed domains: DomainA,DomainB]|[returnTo]'; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /plugins/auth/lib/otp/method_totp.php: -------------------------------------------------------------------------------- 1 | verify($otp); 19 | } 20 | 21 | public static function getPeriod(): int 22 | { 23 | // default period is 30s and digest is sha1. Google Authenticator is restricted to this settings 24 | return 30; 25 | } 26 | 27 | public static function getloginTries(): int 28 | { 29 | return 10; 30 | } 31 | 32 | public function getProvisioningUri(rex_ycom_user $user): string 33 | { 34 | // create a uri with a random secret 35 | $otp = TOTP::create(null, self::getPeriod()); 36 | 37 | // the label rendered in "Google Authenticator" or similar app 38 | $label = $user->getValue('login') . '@' . rex::getServerName() . ' (' . $_SERVER['HTTP_HOST'] . ')'; 39 | $label = str_replace(':', '_', $label); // colon is forbidden 40 | $otp->setLabel($label); 41 | $otp->setIssuer(str_replace(':', '_', $user->getValue('login'))); 42 | 43 | return $otp->getProvisioningUri(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /plugins/auth/lib/yform/value/ycom_auth_returnto.php: -------------------------------------------------------------------------------- 1 | www.yakamara.de 8 | */ 9 | 10 | class rex_yform_value_ycom_auth_returnto extends rex_yform_value_abstract 11 | { 12 | public function enterObject(): void 13 | { 14 | $returnTo = $this->getValue(); 15 | 16 | $returnTos = []; 17 | $returnTos[] = (string) $returnTo; 18 | $returnTos[] = rex_request('returnTo', 'string'); 19 | $returnTos[] = $this->getElement(3); 20 | $returnTos[] = rex_getUrl(rex_ycom_config::get('article_id_jump_ok'), '', [], '&'); 21 | $allowedDomains = ('' != $this->getElement(2)) ? explode(',', $this->getElement(2)) : []; 22 | $returnTo = rex_ycom_auth::getReturnTo($returnTos, $allowedDomains); 23 | 24 | $this->setValue($returnTo); 25 | 26 | if ($this->needsOutput()) { 27 | $this->params['form_output'][$this->getId()] = $this->parse('value.hidden.tpl.php'); 28 | } 29 | 30 | $this->params['value_pool']['email'][$this->getName()] = $this->getValue(); 31 | } 32 | 33 | public function executeAction(): void 34 | { 35 | if ('' != $this->getValue()) { 36 | header('Location: ' . $this->getValue()); 37 | $this->params['form_exit'] = true; 38 | } 39 | } 40 | 41 | public function getDescription(): string 42 | { 43 | return 'ycom_auth_returnto|label|[allowed domains: DomainA,DomainB]|[URL]'; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /.tools/rexstan.php: -------------------------------------------------------------------------------- 1 | getPath('docs') . '/*.md') ?: [] as $file) { 10 | $mdFiles[mb_substr(basename($file), 0, -3)] = $file; 11 | } 12 | 13 | $currenMDFile = rex_request('mdfile', 'string', '01_intro'); 14 | if (!array_key_exists($currenMDFile, $mdFiles)) { 15 | $currenMDFile = '01_intro'; 16 | } 17 | 18 | $page = rex_be_controller::getPageObject('ycom/docs'); 19 | 20 | if (null !== $page) { 21 | foreach ($mdFiles as $key => $mdFile) { 22 | $keyWithoudPrio = mb_substr($key, 3); 23 | $page->addSubpage( 24 | (new rex_be_page($key, rex_i18n::msg('ycom_docs_' . $keyWithoudPrio))) 25 | ->setSubPath($mdFile) 26 | ->setHref('index.php?page=ycom/docs&mdfile=' . $key) 27 | ->setIsActive($key === $currenMDFile), 28 | ); 29 | } 30 | } 31 | 32 | echo rex_view::title($this->i18n('ycom_title')); 33 | 34 | [$Toc, $Content] = rex_markdown::factory()->parseWithToc(rex_file::require($mdFiles[$currenMDFile]), 2, 3, [ 35 | rex_markdown::SOFT_LINE_BREAKS => false, 36 | rex_markdown::HIGHLIGHT_PHP => true, 37 | ]); 38 | 39 | $fragment = new rex_fragment(); 40 | $fragment->setVar('content', $Content, false); 41 | $fragment->setVar('toc', $Toc, false); 42 | $content = $fragment->parse('core/page/docs.php'); 43 | 44 | $fragment = new rex_fragment(); 45 | $fragment->setVar('title', rex_i18n::msg('package_help') . ' ', false); 46 | $fragment->setVar('body', $content, false); 47 | echo $fragment->parse('core/page/section.php'); 48 | -------------------------------------------------------------------------------- /plugins/auth/lib/yform/action/ycom_auth_db.php: -------------------------------------------------------------------------------- 1 | getElement(2); 18 | 19 | switch ($action) { 20 | case 'delete': 21 | rex_ycom_log::log($user, rex_ycom_log::TYPE_LOGIN_DELETED, [ 22 | 'self delete', 23 | ]); 24 | rex_ycom_auth::deleteUser($user->getValue('id')); 25 | rex_ycom_auth::clearUserSession(); 26 | 27 | break; 28 | case 'update': 29 | default: 30 | rex_ycom_log::log($user, rex_ycom_log::TYPE_LOGIN_UPDATED, [ 31 | 'self update', 32 | ]); 33 | 34 | $this->params['main_table'] = rex_ycom_user::table()->getTableName(); 35 | $this->params['main_where'] = 'id=' . (int) (rex_ycom_user::getMe() ? rex_ycom_user::getMe()->getId() : 0); 36 | 37 | $this->setElement(2, ''); 38 | $this->setElement(3, 'main_where'); 39 | 40 | parent::executeAction(); 41 | } 42 | } 43 | 44 | public function getDescription(): string 45 | { 46 | return 'action|ycom_auth_db|update(default)/delete'; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/yform/value/ycom_user.php: -------------------------------------------------------------------------------- 1 | getElement(6); 9 | 10 | $this->setValue(-1); 11 | if (null !== rex_ycom_user::getMe()) { 12 | $this->setValue(rex_ycom_user::getMe()->getValue($this->getElement(2))); 13 | $show_value = rex_ycom_user::getMe()->getValue($show_label); 14 | } 15 | 16 | $wc = ''; 17 | if (isset($this->params['warning'][$this->getId()])) { 18 | $wc = $this->params['warning'][$this->getId()]; 19 | } 20 | 21 | if ('hidden' !== trim($this->getElement(4))) { 22 | $this->params['form_output'][$this->getId()] = ' 23 |24 | 25 | 26 |
'; 27 | } 28 | 29 | $this->params['value_pool']['email'][$this->getElement(1)] = stripslashes($this->getValue()); 30 | if ('no_db' !== $this->getElement(5)) { 31 | $this->params['value_pool']['sql'][$this->getElement(1)] = $this->getValue(); 32 | } 33 | } 34 | 35 | public function getDescription(): string 36 | { 37 | return 'ycom_user -> Beispiel: ycom_user|label|dbfield|Fieldlabel|hidden|[no_db]|showlabel'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /plugins/auth/lang/pt_br.lang: -------------------------------------------------------------------------------- 1 | ycom_auth_title = Autentificação 2 | 3 | ycom_auth_settings = Configurações 4 | ycom_auth_description = Explicação 5 | 6 | ycom_auth_config = Configuração 7 | ycom_auth_config_save = Salvar configuração 8 | ycom_auth_config_status = Status 9 | ycom_auth_config_security = Segurança 10 | ycom_auth_config_forwarder = Seguir para o produto 11 | ycom_auth_config_login_field = Campo para login 12 | 13 | ycom_auth_config_status_authactive = Autentificação ativa 14 | ycom_auth_config_status_stayactive = "Permanecer conectado" ativo 15 | ycom_auth_config_security_hashedpasswd = Senhas criptografadas (sha1) 16 | ycom_auth_config_id_jump_ok = ... ao conectar-se com sucesso 17 | ycom_auth_config_id_jump_not_ok = ... ao não se conectar com sucesso 18 | ycom_auth_config_id_jump_logout = ... ao se desconectar 19 | ycom_auth_config_id_jump_denied = ... ao tentar acessar um produto restrito 20 | ycom_auth_config_id_jump_activation_ok = ... ao ativar com sucesso 21 | ycom_auth_config_id_jump_activation_fail = ... quando a ativação não foi bem sucedida 22 | ycom_auth_config_id_jump_newpassword_ok = ... ao resetar a senha com sucesso 23 | ycom_auth_config_id_jump_newpassword_fail = ... ao resetar a senha sem sucesso 24 | 25 | ycom_auth_settings_updated = A configuração foi salva 26 | 27 | ycom_auth_info_title = Explicação 28 | 29 | ycom_auth_perm = Permissões 30 | ycom_auth_update_perm = Atualizar 31 | ycom_auth_perm_updated = Permissões foram atualizadas 32 | 33 | ycom_auth_password_not_updated = Senha não foi atualizada 34 | ycom_auth_password_updated = Senha foi atualizada 35 | ycom_auth_password_exists = A senha já é utilizada 36 | ycom_auth_password_isempty = A senha ainda não é utilizada -------------------------------------------------------------------------------- /plugins/auth/lib/injections/passwordchange.php: -------------------------------------------------------------------------------- 1 | getValue('new_password_required')) { 11 | if ($article_id_password != rex_article::getCurrentId()) { 12 | return rex_getUrl($article_id_password, '', [], '&'); 13 | } 14 | return true; 15 | } 16 | } 17 | return false; 18 | } 19 | 20 | public function getSettingsContent(): string 21 | { 22 | $addon = rex_plugin::get('ycom', 'auth'); 23 | return ' 24 | 36 | '; 37 | } 38 | 39 | public function triggerSaveSettings(): void 40 | { 41 | $addon = rex_plugin::get('ycom', 'auth'); 42 | $addon->setConfig('article_id_jump_password', rex_request('article_id_jump_password', 'int')); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /plugins/auth/lib/injections/termsofuse.php: -------------------------------------------------------------------------------- 1 | getValue('termsofuse_accepted')) { 11 | if ($article_id_termsofuse != rex_article::getCurrentId()) { 12 | return rex_getUrl($article_id_termsofuse, '', [], '&'); 13 | } 14 | return true; 15 | } 16 | } 17 | return false; 18 | } 19 | 20 | public function getSettingsContent(): string 21 | { 22 | $addon = rex_plugin::get('ycom', 'auth'); 23 | return ' 24 | 36 | '; 37 | } 38 | 39 | public function triggerSaveSettings(): void 40 | { 41 | $addon = rex_plugin::get('ycom', 'auth'); 42 | $addon->setConfig('article_id_jump_termsofuse', rex_request('article_id_jump_termsofuse', 'int', 0)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /plugins/group/boot.php: -------------------------------------------------------------------------------- 1 | getSubject(); 15 | $yform->setValueField('choice', [ 16 | 'name' => 'ycom_group_type', 17 | 'label' => rex_i18n::msg('ycom_group_type'), 18 | 'choices' => rex_ycom_group::$perms, 19 | ]); 20 | $yform->setValueField('choice', [ 21 | 'name' => 'ycom_groups', 22 | 'label' => rex_i18n::msg('ycom_groups'), 23 | 'choices' => rex_ycom_group::getGroups(), 24 | 'size' => 5, 25 | 'multiple' => true, 26 | ]); 27 | return $yform; 28 | }); 29 | } 30 | 31 | rex_extension::register('YCOM_AUTH_USER_CHECK', static function (rex_extension_point $ep) { 32 | if (!$ep->getSubject()) { 33 | return false; 34 | } 35 | 36 | /** @var rex_article|rex_category $article */ 37 | $article = $ep->getParam('article'); 38 | 39 | if (1 != $article->getValue('ycom_auth_type')) { 40 | return $ep->getSubject(); 41 | } 42 | 43 | /** @var rex_ycom_user|null $me */ 44 | $me = $ep->getParam('me'); 45 | $type = (string) $article->getValue('ycom_group_type'); 46 | $userGroups = ($me) ? $me->getGroups() : []; 47 | $articleGroups = (string) $article->getValue('ycom_groups'); 48 | 49 | $groups = []; 50 | if ('' != $articleGroups) { 51 | $groups = explode(',', $articleGroups); 52 | } 53 | 54 | return rex_ycom_group::hasGroupPerm($type, $groups, $userGroups); 55 | }); 56 | -------------------------------------------------------------------------------- /assets/ycom_backend.js: -------------------------------------------------------------------------------- 1 | $(document).on('rex:ready', function () { 2 | 3 | // YCom-Artikel Rechte 4 | $('#yform-ycom_auth-perm-ycom_auth_type select,#yform-ycom_auth-perm-ycom_group_type select').on('change', function() { 5 | if($('#yform-ycom_auth-perm-ycom_auth_type select option:selected').val() !== "1") { 6 | $('#yform-ycom_auth-perm-ycom_group_type').hide(); 7 | $('#yform-ycom_auth-perm-ycom_groups').hide(); 8 | } else { 9 | $('#yform-ycom_auth-perm-ycom_group_type').show(); 10 | let group_type = $('#yform-ycom_auth-perm-ycom_group_type option:selected').val(); 11 | if(group_type === "1" || group_type === "2") { 12 | $('#yform-ycom_auth-perm-ycom_groups').show(); 13 | } else { 14 | $('#yform-ycom_auth-perm-ycom_groups').hide(); 15 | } 16 | } 17 | }); 18 | $('#yform-ycom_auth-perm-ycom_auth_type select').trigger('change'); 19 | 20 | // Medienpool Rechte 21 | $('select[name="ycom_auth_type"],select[name="ycom_group_type"]').on('change', function() { 22 | 23 | if($('select[name="ycom_auth_type"] option:selected').val() !== "1") { 24 | $('select[name="ycom_group_type"]').closest('.form-group').hide(); 25 | $('select[name="ycom_groups[]"]').closest('.form-group').hide(); 26 | } else { 27 | $('select[name="ycom_group_type"]').closest('.form-group').show(); 28 | let group_type_selected = $('select[name="ycom_group_type"] option:selected').val(); 29 | if(group_type_selected === "1" || group_type_selected === "2") { 30 | $('select[name="ycom_groups[]"]').closest('.form-group').show(); 31 | } else { 32 | $('select[name="ycom_groups[]"]').closest('.form-group').hide(); 33 | } 34 | } 35 | }); 36 | $('select[name="ycom_auth_type"]').trigger('change'); 37 | }); 38 | -------------------------------------------------------------------------------- /lang/pt_br.lang: -------------------------------------------------------------------------------- 1 | ycom_perm = Permissões comunitárias 2 | 3 | ycom_page_perm = Página de permissões comunitárias 4 | 5 | navigation_ycom = Comunidade 6 | ycom_title = Comunidade: configurações 7 | ycom_navi_title = Configurações 8 | 9 | ycom_main_title = Informações 10 | ycom_info = Readme 11 | ycom_info_title = Informações úteis para trabalhar com o AddOn comunidade 12 | ycom_manual = Manual / Exemplos 13 | ycom_manual_title = Manual / Exemplos 14 | ycom_changelog = Mudar log 15 | ycom_changelog_title = Mudar log 16 | ycom_license = Licença 17 | ycom_license_title = Licença 18 | ycom_overview = Visão geral 19 | ycom_user_management = Gestão de usuário 20 | ycom_field_management = Editar campos 21 | 22 | ycom_user = Usuário 23 | yform_ycom_user = Usuário de comunidade 24 | rex_ycom_user = Usuário de comunidade 25 | 26 | email = E-mail 27 | status = Status 28 | firstname = Primeiro Nome 29 | activation_key = Chave de ativação 30 | session_key = Chave da seção 31 | last_login_time = Último acesso 32 | last_action_time = Última ação 33 | login_failed = Logins falhos 34 | login_tries = Tentativas de login 35 | 36 | ycom_login_tries_info = 10 tentativas falhas de logon causam o bloqueamente do usuário. 37 | 38 | ycom_account_inactive = Acesso desativado 39 | ycom_account_requested = Acesso requisitado 40 | ycom_account_active = Acesso ativo 41 | 42 | ycom_status = Status 43 | 44 | ycom_perm_type = Permissões da página 45 | 46 | ycom_perm_extends = Adotar categoria mais ampla, caso contrário acessível a todos os usuários 47 | ycom_perm_only_logged_in = Acesso para usuários loggados 48 | ycom_perm_only_not_logged_in = Acesso para todos os usuários não loggados 49 | ycom_perm_all = Acesso para todos os usuários 50 | 51 | ycom_this_login_exists_already = Este nome de usuário já existe 52 | ycom_this_email_exists_already = Este e-mail de usuário já existe 53 | ycom_please_enter_login = Por favor, insira um nome de usuário 54 | ycom_please_enter_email = Por favo, insira um endereço de e-mail -------------------------------------------------------------------------------- /docs/04_navigations.md: -------------------------------------------------------------------------------- 1 | # Navigationen 2 | 3 | ## Benutzung der REDAXO Navigation 4 | 5 | Damit die Userberechtigungen in der Navigation berücksichtigt werden muss die REDAXO Klasse rex_navigation::factory ergänzt werden. 6 | 7 | ```php 8 | $nav = rex_navigation::factory(); 9 | $nav->addCallback('rex_ycom_auth::articleIsPermitted'); 10 | $nav->show(0, 1, TRUE, TRUE); 11 | ``` 12 | 13 | > **Hinweis:** Die Ausgabe der Navigation kann angepasst und um Parameter erweitert werden. Details siehe in der Doku:' . $addon->i18n('no_permission_to_edit') . '
|
|1 76 | 77 | // Brauche User_ID, HASH 78 | // Passwort zurücksetzen, Register, email_change, Newsletter? 79 | // Ans Templatesystem andocken und eigene Kennung bauen REX_YCOM[tokenlink] 80 | 81 | // ycom_token|password_reset 82 | 83 | // UserToken=[Token][NonDBToken][id] 84 | // Tokenvalidierung 85 | // Form ausführbar, wenn Token valide und danach, wenn Formular ausgeführt wurde, Token löschen 86 | // ycom_token_validate (request und hidden value wenn abgeschickt) 87 | 88 | // REX_YCOM[id, token] 89 | 90 | // Passwort vergessen / email + id 91 | // Registrierung / email + id 92 | // E-Mail-Änderung / email + id 93 | -------------------------------------------------------------------------------- /lib/ycom_log.php: -------------------------------------------------------------------------------- 1 | isAvailable()) { 27 | $addon->setConfig('log', 1); 28 | self::$active = true; 29 | } 30 | } 31 | 32 | public static function deactivate(): void 33 | { 34 | $addon = rex_addon::get('ycom'); 35 | if ($addon->isAvailable()) { 36 | $addon->setConfig('log', 0); 37 | self::$active = false; 38 | } 39 | } 40 | 41 | public static function isActive(): bool 42 | { 43 | if (null === self::$active) { 44 | $addon = rex_addon::get('ycom'); 45 | if ($addon->isAvailable()) { 46 | self::$active = (1 === $addon->getConfig('log')) ? true : false; 47 | } else { 48 | self::$active = false; 49 | } 50 | } 51 | return (self::$active) ? true : false; 52 | } 53 | 54 | public static function logFolder(): string 55 | { 56 | return rex_path::addonData('ycom', 'log'); 57 | } 58 | 59 | public static function logFile(): string 60 | { 61 | return rex_path::log('ycom_user.log'); 62 | } 63 | 64 | public static function delete(): bool 65 | { 66 | return rex_log_file::delete(self::logFile()); 67 | } 68 | 69 | /** 70 | * @param rex_ycom_user|string|rex_yform_manager_dataset $user 71 | * @param array| ' . rex_i18n::msg('ycom_user_log_time') . ' | 37 |' . rex_i18n::msg('ycom_user_log_ip') . ' | 38 |' . rex_i18n::msg('ycom_user_log_user_id') . ' | 39 |' . rex_i18n::msg('ycom_auth_config_login_field') . ' | 40 |' . rex_i18n::msg('ycom_user_log_type') . ' | 41 |' . rex_i18n::msg('ycom_user_log_params') . ' | 42 |
|---|---|---|---|---|---|
| ' . rex_formatter::intlDateTime($entry->getTimestamp(), [IntlDateFormatter::SHORT, IntlDateFormatter::MEDIUM]) . ' | 53 |' . rex_escape($data[0]) . ' | 54 |' . rex_escape($data[1]) . ' | 55 |' . rex_escape($data[2]) . ' | 56 |' . rex_escape($data[3]) . ' | 57 |' . rex_escape($data[4] ?? '') . ' | 58 |
Hier auslesen welche Parameter übergeben werden und eventuell übernehmen/auswerten
'; 40 | echo 'Danach diesen Block löschen
'; 41 | echo 'Das hier ist bereits erkannt worden
'; 42 | dump($data); 43 | echo 'Das hier kam über die SAML Schnittstelle
'; 44 | dump($Userdata); 45 | 46 | exit; 47 | 48 | // z.B. 49 | $emailKey = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'; 50 | $givennameKey = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname'; 51 | $surnameKey = 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname'; 52 | 53 | $data['email'] = @$Userdata[$emailKey][0]; 54 | 55 | // Userdatensatz mit gewünschten Einstellungen anreichern. 56 | $data['termsofuse_accepted'] = 1; 57 | $data['login_tries'] = 0; 58 | 59 | return $data; 60 | 61 | }); 62 | ``` 63 | 64 | ## CAS 65 | 66 | ## OAuth2 67 | 68 | ## Allgemeines 69 | 70 | ### Programmatisches Einloggen an der Authentifizierung vorbei 71 | 72 | Hat man einen eigenen Authentifizierungsmechanismus implementiert, so genügt es, den gewünschten YCom-User über dessen ID einzuloggen: 73 | 74 | ```php 75 | $user = rex_ycom_auth::loginWithParams(['login' => $user_id]) 76 | ``` 77 | 78 | ### Loginseite 79 | 80 | Sofern man die externe Authentifikation nicht nutzt, wird die Loginseite meistens so eingestellt, dass nur nicht eingeloggte User diese sehen können. Das ist hier nicht zu empfehlen, da man sich nicht einloggen kann, wenn man über den IdentityProvider zur REDAXO Community kommt und bereits eingeloggt ist. Deswegen sollte die Loginseite verfühgbar, aber nicht sichtbar in der Navigation sein, wenn man eingeloggt ist. 81 | 82 | -------------------------------------------------------------------------------- /plugins/auth/install.php: -------------------------------------------------------------------------------- 1 | hasColumn('ycom_auth_type')) { 12 | $Column = $articleTable->getColumn('ycom_auth_type'); 13 | if (null !== $Column && 'enum' === substr($Column->getType(), 0, 4)) { 14 | $articleAuthTypeWasEnum = true; 15 | } 16 | } 17 | 18 | rex_sql_table::get(rex::getTable('article')) 19 | ->ensureColumn(new rex_sql_column('ycom_auth_type', 'int', false, '0')) 20 | ->alter(); 21 | 22 | rex_sql_table::get(rex::getTable('ycom_user_token')) 23 | ->ensureColumn(new rex_sql_column('hash', 'varchar(255)')) 24 | ->ensureColumn(new rex_sql_column('user_id', 'int(10) unsigned', true)) 25 | ->ensureColumn(new rex_sql_column('email', 'varchar(255)')) 26 | ->ensureColumn(new rex_sql_column('type', 'varchar(255)')) 27 | ->ensureColumn(new rex_sql_column('selector', 'varchar(255)')) 28 | ->ensureColumn(new rex_sql_column('createdate', 'datetime')) 29 | ->ensureColumn(new rex_sql_column('expiredate', 'datetime')) 30 | ->setPrimaryKey('hash') 31 | ->ensureIndex(new rex_sql_index('token', ['selector'], rex_sql_index::UNIQUE)) 32 | ->ensureForeignKey( 33 | new rex_sql_foreign_key( 34 | 'ycom_user_token_id', 35 | rex::getTable('ycom_user'), 36 | ['user_id' => 'id'], 37 | rex_sql_foreign_key::CASCADE, 38 | rex_sql_foreign_key::CASCADE, 39 | ), 40 | ) 41 | ->ensure(); 42 | 43 | rex_sql_table::get(rex::getTable('ycom_user_session')) 44 | ->ensureColumn(new rex_sql_column('session_id', 'varchar(255)')) 45 | ->ensureColumn(new rex_sql_column('user_id', 'int(10) unsigned')) 46 | ->ensureColumn(new rex_sql_column('ip', 'varchar(39)')) // max for ipv6 47 | ->ensureColumn(new rex_sql_column('useragent', 'varchar(255)')) 48 | ->ensureColumn(new rex_sql_column('starttime', 'datetime')) 49 | ->ensureColumn(new rex_sql_column('last_activity', 'datetime')) 50 | ->ensureColumn(new rex_sql_column('last_activity', 'datetime')) 51 | ->ensureColumn(new rex_sql_column('otp_verified', 'tinyint(1)', false, '0')) 52 | ->ensureColumn(new rex_sql_column('cookie_key', 'varchar(255)', true)) 53 | ->ensureIndex(new rex_sql_index('cookie_key', ['cookie_key'], rex_sql_index::UNIQUE)) 54 | ->setPrimaryKey('session_id') 55 | ->ensureForeignKey( 56 | new rex_sql_foreign_key( 57 | 'ycom_user_session_id', 58 | rex::getTable('ycom_user'), 59 | ['user_id' => 'id'], 60 | rex_sql_foreign_key::CASCADE, 61 | rex_sql_foreign_key::CASCADE, 62 | ), 63 | ) 64 | ->ensure(); 65 | 66 | // Update from Version < 4 67 | if ($articleAuthTypeWasEnum) { 68 | rex_sql::factory()->setQuery('UPDATE rex_article SET `ycom_auth_type` = `ycom_auth_type` -1'); 69 | } 70 | 71 | foreach (['saml', 'oauth2', 'cas'] as $settingType) { 72 | $pathFrom = __DIR__ . '/install/' . $settingType . '.php'; 73 | $pathTo = rex_addon::get('ycom')->getDataPath($settingType . '.php'); 74 | if (!file_exists($pathTo)) { 75 | rex_file::copy($pathFrom, $pathTo); 76 | } 77 | } 78 | 79 | // termofuse -> termsofuse. Version < 3.0 80 | try { 81 | rex_sql_table::get(rex::getTablePrefix() . 'ycom_user') 82 | ->ensureColumn(new rex_sql_column('termsofuse_accepted', 'tinyint(1)', false, '0')) 83 | ->removeColumn('session_key') 84 | ->alter(); 85 | 86 | rex_sql::factory() 87 | // ->setQuery('alter table `' . rex::getTablePrefix().'ycom_user' . '` drop if exists `termofuse_accepted`', []) 88 | ->setQuery('delete from `' . rex_yform_manager_field::table() . '` where `table_name`="rex_ycom_user" and `type_id`="value" and `type_name`="checkbox" and `name`="termofuse_accepted"', []) 89 | ->setQuery('UPDATE `rex_config` AS target LEFT JOIN `rex_config` AS existing ON existing.key = "article_id_jump_termsofuse" AND existing.namespace = "ycom/auth" SET target.key = "article_id_jump_termsofuse" WHERE target.key = "article_id_jump_termofuse" AND target.namespace = "ycom/auth" AND existing.key IS NULL', []) 90 | ->setQuery('delete from `' . rex_yform_manager_field::table() . '` where `table_name`="rex_ycom_user" and `type_id`="value" and `type_name`="generate_key" and `name`="session_key"'); 91 | } catch (rex_sql_exception $e) { 92 | dump($e); 93 | exit; 94 | } 95 | -------------------------------------------------------------------------------- /.github/workflows/rexstan.yml: -------------------------------------------------------------------------------- 1 | name: rexstan 2 | 3 | on: 4 | push: 5 | branches: [ master, main ] 6 | pull_request: 7 | branches: [ master, main ] 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | rexstan: 14 | env: 15 | ADDON_KEY: ${{ github.event.repository.name }} 16 | 17 | runs-on: ubuntu-latest 18 | permissions: 19 | contents: write # for Git to git apply 20 | 21 | steps: 22 | - uses: actions/checkout@v3 23 | 24 | # setup PHP v8, install some extensions 25 | - name: Setup PHP 26 | uses: shivammathur/setup-php@v2 27 | with: 28 | php-version: '8.2' 29 | extensions: gd, intl, pdo_mysql 30 | coverage: none # disable xdebug, pcov 31 | 32 | # download the latest REDAXO release and unzip it 33 | # credits https://blog.markvincze.com/download-artifacts-from-a-latest-github-release-in-sh-and-powershell/ 34 | - name: Download latest REDAXO release 35 | run: | 36 | LATEST_RELEASE=$(curl -L -s -H 'Accept: application/json' https://github.com/redaxo/redaxo/releases/latest) 37 | REDAXO_VERSION=$(echo $LATEST_RELEASE | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/') 38 | echo "Downloaded REDAXO $REDAXO_VERSION" 39 | curl -Ls -o redaxo.zip https://github.com/redaxo/redaxo/releases/download/$REDAXO_VERSION/redaxo_$REDAXO_VERSION.zip 40 | unzip -oq redaxo.zip -d redaxo_cms 41 | rm redaxo.zip 42 | 43 | # start mysql service, create a database called redaxo5, apply config patch 44 | - name: Init database 45 | run: | 46 | sudo /etc/init.d/mysql start 47 | mysql -uroot -h127.0.0.1 -proot -e 'create database redaxo5;' 48 | 49 | # run REDAXO setup with the following parameters 50 | # Language: de 51 | # DB password: root 52 | # Create DB: no 53 | # Admin username: admin 54 | # Admin password: adminpassword 55 | # Error E-mail: test@redaxo.invalid 56 | - name: Setup REDAXO 57 | run: | 58 | php redaxo_cms/redaxo/bin/console setup:run -n --lang=de_de --agree-license --db-host=127.0.0.1 --db-name=redaxo5 --db-password=root --db-createdb=no --db-setup=normal --admin-username=admin --admin-password=adminpassword --error-email=test@redaxo.invalid --ansi 59 | php redaxo_cms/redaxo/bin/console config:set --type boolean debug.enabled true 60 | php redaxo_cms/redaxo/bin/console config:set --type boolean debug.throw_always_exception true 61 | 62 | # copy Addon files, ignore some directories... 63 | # install the addon 64 | # if the addon name does not match the repository name, ${{ github.event.repository.name }} must be replaced with the addon name 65 | # install latest rexstan 66 | # if additional addons are needed, they can be installed via the console commands 67 | # see: https://www.redaxo.org/doku/main/basis-addons#console 68 | - name: Copy and install Addons 69 | run: | 70 | rsync -av --exclude='./vendor' --exclude='.github' --exclude='.git' --exclude='redaxo_cms' './' 'redaxo_cms/redaxo/src/addons/${{ github.event.repository.name }}' 71 | redaxo_cms/redaxo/bin/console install:download 'rexstan' '1.*' 72 | redaxo_cms/redaxo/bin/console package:install 'rexstan' 73 | redaxo_cms/redaxo/bin/console package:install 'cronjob' 74 | redaxo_cms/redaxo/bin/console package:install 'phpmailer' 75 | redaxo_cms/redaxo/bin/console install:download 'yform' '4.*' 76 | redaxo_cms/redaxo/bin/console package:install 'yform' 77 | redaxo_cms/redaxo/bin/console install:download 'yrewrite' '2.*' 78 | redaxo_cms/redaxo/bin/console package:install 'yrewrite' 79 | redaxo_cms/redaxo/bin/console package:install '${{ github.event.repository.name }}' 80 | 81 | # install dependencies from composer.json 82 | - name: Install test dependencies 83 | working-directory: redaxo_cms/redaxo/src/addons/${{ github.event.repository.name }} 84 | env: 85 | COMPOSER: composer.json 86 | run: composer install --prefer-dist --no-progress 87 | 88 | # execute rexstan.php to create the needed user-config.neon 89 | - name: Execute .tools/rexstan.php 90 | run: php -f redaxo/src/addons/${{ github.event.repository.name }}/.tools/rexstan.php 91 | working-directory: redaxo_cms 92 | 93 | # run rexstan 94 | - id: rexstan 95 | name: Run rexstan 96 | run: redaxo_cms/redaxo/bin/console rexstan:analyze 97 | -------------------------------------------------------------------------------- /plugins/auth/lib/otp/password_config.php: -------------------------------------------------------------------------------- 1 | user = $user; 20 | } 21 | 22 | public static function forCurrentUser(): self 23 | { 24 | $user = rex_ycom_auth::getUser(); 25 | return self::forUser($user); 26 | } 27 | 28 | public static function forUser(rex_ycom_user $user): self 29 | { 30 | return self::fromJson($user->getValue('otp_config'), $user); 31 | } 32 | 33 | public static function loadFromDb(rex_ycom_otp_method_interface $method, rex_ycom_user $user): self 34 | { 35 | // get non-cached values 36 | $userSql = rex_sql::factory(); 37 | $userSql->setTable(rex::getTablePrefix() . 'ycom_user'); 38 | $userSql->setWhere(['id' => $user->getId()]); 39 | $userSql->select(); 40 | 41 | $json = (string) $userSql->getValue('otp_config'); 42 | $config = self::fromJson($json, $user); 43 | $config->method = $method instanceof rex_ycom_otp_method_email ? 'email' : 'totp'; 44 | if (null === $config->getProvisioningUri()) { 45 | $config->setProvisioningUri($method->getProvisioningUri($user)); 46 | } 47 | return $config; 48 | } 49 | 50 | private static function fromJson(?string $json, rex_ycom_user $user): self 51 | { 52 | if (is_string($json)) { 53 | $configArr = json_decode($json, true); 54 | 55 | if (is_array($configArr)) { 56 | // compat with older versions, which did not yet define a method 57 | if (!array_key_exists('method', $configArr)) { 58 | $configArr['method'] = 'totp'; 59 | } 60 | 61 | $config = new self($user); 62 | $config->provisioningUri = $configArr['provisioningUri']; 63 | $config->enabled = $configArr['enabled']; 64 | $config->method = $configArr['method']; 65 | return $config; 66 | } 67 | } 68 | 69 | $method = new rex_ycom_otp_method_totp(); 70 | 71 | $default = new self($user); 72 | $default->method = $method instanceof rex_ycom_otp_method_email ? 'email' : 'totp'; 73 | $default->provisioningUri = $method->getProvisioningUri($user); 74 | 75 | return $default; 76 | } 77 | 78 | public function isEnabled(): bool 79 | { 80 | return $this->enabled ? true : false; 81 | } 82 | 83 | public function enable(): self 84 | { 85 | $this->enabled = true; 86 | return $this; 87 | } 88 | 89 | public function disable(): self 90 | { 91 | $this->enabled = false; 92 | $this->provisioningUri = null; 93 | return $this; 94 | } 95 | 96 | public function updateMethod(rex_ycom_otp_method_interface $method): self 97 | { 98 | $this->method = $method instanceof rex_ycom_otp_method_email ? 'email' : 'totp'; 99 | $this->provisioningUri = $method->getProvisioningUri($this->user); 100 | return $this; 101 | } 102 | 103 | public function getProvisioningUri() 104 | { 105 | return $this->provisioningUri; 106 | } 107 | 108 | public function setProvisioningUri($provisioningUri): self 109 | { 110 | $this->provisioningUri = $provisioningUri; 111 | return $this; 112 | } 113 | 114 | public function getMethod() 115 | { 116 | return $this->method; 117 | } 118 | 119 | public function save(): void 120 | { 121 | echo ''; 122 | debug_print_backtrace(); 123 | echo ''; 124 | 125 | $userSql = rex_sql::factory(); 126 | $userSql->setTable(rex::getTablePrefix() . 'ycom_user'); 127 | $userSql->setWhere(['id' => $this->user->getId()]); 128 | $userSql->setValue('otp_config', json_encode( 129 | [ 130 | 'provisioningUri' => $this->provisioningUri, 131 | 'method' => $this->method, 132 | 'enabled' => $this->enabled, 133 | ], 134 | )); 135 | $userSql->update(); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /.github/workflows/phpunit.yml: -------------------------------------------------------------------------------- 1 | name: PHPUnit 2 | 3 | on: 4 | push: 5 | branches: [ master, main ] 6 | pull_request: 7 | branches: [ master, main ] 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | phpunit: 14 | 15 | runs-on: ubuntu-latest 16 | permissions: 17 | contents: write # for Git to git apply 18 | 19 | steps: 20 | - uses: actions/checkout@v3 21 | 22 | # setup PHP v8, install some extensions 23 | - name: Setup PHP 24 | uses: shivammathur/setup-php@v2 25 | with: 26 | php-version: '8.2' 27 | extensions: gd, intl, pdo_mysql 28 | coverage: none # disable xdebug, pcov 29 | 30 | # download the latest REDAXO release and unzip it 31 | # credits https://blog.markvincze.com/download-artifacts-from-a-latest-github-release-in-sh-and-powershell/ 32 | - name: Download latest REDAXO release 33 | run: | 34 | LATEST_RELEASE=$(curl -L -s -H 'Accept: application/json' https://github.com/redaxo/redaxo/releases/latest) 35 | REDAXO_VERSION=$(echo $LATEST_RELEASE | sed -e 's/.*"tag_name":"\([^"]*\)".*/\1/') 36 | echo "Downloaded REDAXO $REDAXO_VERSION" 37 | curl -Ls -o redaxo.zip https://github.com/redaxo/redaxo/releases/download/$REDAXO_VERSION/redaxo_$REDAXO_VERSION.zip 38 | unzip -oq redaxo.zip -d redaxo_cms 39 | rm redaxo.zip 40 | 41 | # start mysql service, create a database called redaxo5, apply config patch 42 | - name: Init database 43 | run: | 44 | sudo /etc/init.d/mysql start 45 | mysql -uroot -h127.0.0.1 -proot -e 'create database redaxo5;' 46 | 47 | # run REDAXO setup with the following parameters 48 | # Language: de 49 | # DB password: root 50 | # Create DB: no 51 | # Admin username: admin 52 | # Admin password: adminpassword 53 | # Error E-mail: test@redaxo.invalid 54 | - name: Setup REDAXO 55 | run: | 56 | php redaxo_cms/redaxo/bin/console setup:run -n --lang=de_de --agree-license --db-host=127.0.0.1 --db-name=redaxo5 --db-password=root --db-createdb=no --db-setup=normal --admin-username=admin --admin-password=adminpassword --error-email=test@redaxo.invalid --ansi 57 | php redaxo_cms/redaxo/bin/console config:set --type boolean debug.enabled true 58 | php redaxo_cms/redaxo/bin/console config:set --type boolean debug.throw_always_exception true 59 | 60 | # copy Addon files, ignore some directories... 61 | # install the addon 62 | # if the addon name does not match the repository name, ${{ github.event.repository.name }} must be replaced with the addon name 63 | # if additional addons are needed, they can be installed via the console commands 64 | # see: https://www.redaxo.org/doku/main/basis-addons#console 65 | - name: Copy and install Addons 66 | run: | 67 | rsync -av --exclude='./vendor' --exclude='.github' --exclude='.git' --exclude='redaxo_cms' './' 'redaxo_cms/redaxo/src/addons/${{ github.event.repository.name }}' 68 | redaxo_cms/redaxo/bin/console package:install 'cronjob' 69 | redaxo_cms/redaxo/bin/console package:install 'phpmailer' 70 | redaxo_cms/redaxo/bin/console install:download 'yform' '4.*' 71 | redaxo_cms/redaxo/bin/console package:install 'yform' 72 | redaxo_cms/redaxo/bin/console install:download 'yrewrite' '2.*' 73 | redaxo_cms/redaxo/bin/console package:install 'yrewrite' 74 | redaxo_cms/redaxo/bin/console package:install '${{ github.event.repository.name }}' 75 | 76 | # install dependencies from composer.json 77 | - name: Install test dependencies 78 | working-directory: redaxo_cms/redaxo/src/addons/${{ github.event.repository.name }} 79 | env: 80 | COMPOSER: composer.json 81 | run: composer install --prefer-dist --no-progress 82 | 83 | - name: Setup Problem Matchers for PHPUnit 84 | run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" 85 | 86 | # run unit tests, see composer.json 87 | - name: Run phpunit 88 | working-directory: redaxo_cms/redaxo/src/addons/${{ github.event.repository.name }} 89 | run: composer unit-test 90 | -------------------------------------------------------------------------------- /plugins/auth/pages/sessions.php: -------------------------------------------------------------------------------- 1 | i18n('ycom_title')); 6 | 7 | rex_ycom_user_session::clearExpiredSessions(); 8 | 9 | $func = rex_request('func', 'string', ''); 10 | switch ($func) { 11 | case 'ycom_user_delete_sessions': 12 | $amount = (int) rex_ycom_user_session::deleteAllSessions(); 13 | echo rex_view::success($this->i18n('sessions_deleted', $amount)); 14 | break; 15 | case 'remove_session': 16 | // delete session. 17 | $session_id = (string) rex_request('session_id', 'string', ''); 18 | $user_id = (string) rex_request::get('user_id', 'string', 0); 19 | rex_ycom_user_session::getInstance()->removeSession($session_id, $user_id); 20 | echo rex_view::success($this->i18n('session_removed')); 21 | break; 22 | case 'create_session': 23 | $user_id = (int) rex_request::get('user_id', 'int', 0); 24 | $ycom_user = rex_ycom_user::get($user_id); 25 | if (null !== $ycom_user) { 26 | if (1 > $ycom_user->getValue('status')) { 27 | echo rex_view::error(rex_i18n::rawMsg('ycom_session_could_not_been_added')); 28 | } else { 29 | $_SESSION[rex::getProperty('instname')][rex_ycom_auth::$sessionKey] = [ 30 | 'UID' => $ycom_user->getId(), 31 | ]; 32 | rex_ycom_user_session::getInstance()->storeCurrentSession($ycom_user); 33 | echo rex_view::success(rex_i18n::rawMsg('ycom_session_added_ready_to_login', rex_getUrl(rex_ycom_config::get('article_id_jump_ok')))); 34 | 35 | $be_user = rex::getUser(); 36 | if (null !== $be_user) { 37 | rex_ycom_log::log( 38 | $ycom_user, 39 | rex_ycom_log::TYPE_IMPERSONATE, 40 | [ 41 | 'be_user_id' => $be_user->getValue('id'), 42 | 'be_user_login' => $be_user->getValue('login'), 43 | 'be_user_name' => $be_user->getValue('name'), 44 | 'be_user_email' => $be_user->getValue('email'), 45 | ], 46 | ); 47 | } 48 | } 49 | } 50 | break; 51 | } 52 | 53 | echo rex_view::warning(rex_i18n::rawMsg('ycom_user_session_delete_all_sessions_link', rex_url::currentBackendPage() . '&func=ycom_user_delete_sessions')); 54 | 55 | $list = rex_list::factory('SELECT session_id, cookie_key, ip, user_id, useragent, starttime, last_activity from ' . rex::getTablePrefix() . 'ycom_user_session ORDER BY last_activity DESC'); 56 | 57 | $list->addColumn('remove_session', '', 0, ['