Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enh: Configuration Settings #3

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open

Conversation

ArchBlood
Copy link

Resolves: #2

@ArchBlood ArchBlood marked this pull request as draft November 10, 2023 11:13
@ArchBlood
Copy link
Author

This is how it looks after implementation;

Screenshot_1

@ArchBlood ArchBlood marked this pull request as ready for review November 10, 2023 15:06
@ArchBlood
Copy link
Author

Seems like it still throws Error: Typed property humhub\modules\sso\jwt\models\Configuration::$settingsManager must not be accessed before initialization 🤔

@ArchBlood
Copy link
Author

Seems like it still throws Error: Typed property humhub\modules\sso\jwt\models\Configuration::$settingsManager must not be accessed before initialization 🤔

This error only happens for guest when the login modal is activated it seems.

@ArchBlood
Copy link
Author

Currently still unable to fix this issue, not sure why it's showing up other than autoLogin possibly being the problem.

@ArchBlood
Copy link
Author

[So after fixing some of the issues it seems that get() throws the following error now;

Error: Call to a member function get() on null in /home/greenmet/public_html/protected/modules/jwt-sso/models/Configuration.php:120

From what I'm getting it seems that get() must be a string type and can't be anything else?

https://github.com/humhub/humhub/blob/ae8f2fa34255a33aff639fb5a5cfde65d39a33c9/protected/humhub/components/SettingsManager.php#L150-L158

@ArchBlood
Copy link
Author

@luke- from looking at this deeper, it's not possible to implement it in this way, I can implement it through settings but not settingsManager

@ArchBlood ArchBlood marked this pull request as draft January 9, 2024 08:41
@ArchBlood
Copy link
Author

@yurabakhtin could you look over this to see if I made any errors within the code? At the moment I'm completely stumped. 🤔

@yurabakhtin
Copy link
Contributor

could you look over this to see if I made any errors within the code? At the moment I'm completely stumped. 🤔

@ArchBlood If you tell about this error:

Seems like it still throws Error: Typed property humhub\modules\sso\jwt\models\Configuration::$settingsManager must not be accessed before initialization 🤔

then please try to update the code public SettingsManager $settingsManager; to public $settingsManager;
or to public ?SettingsManager $settingsManager = null;.

@ArchBlood
Copy link
Author

could you look over this to see if I made any errors within the code? At the moment I'm completely stumped. 🤔

@ArchBlood If you tell about this error:

Seems like it still throws Error: Typed property humhub\modules\sso\jwt\models\Configuration::$settingsManager must not be accessed before initialization 🤔

then please try to update the code public SettingsManager $settingsManager; to public $settingsManager; or to public ?SettingsManager $settingsManager = null;.

Using public ?SettingsManager $settingsManager = null; provides the following error for enable state when visiting the site;

Error: Call to a member function get() on null in /home/greenmet/public_html/protected/modules/jwt-sso/models/Configuration.php:121

I've changed the loadBySettings() to the following which fixes the null returns;

    public function loadBySettings()
    {
        if ($this->settingsManager !== null) {
            $this->enabled = (bool)$this->settingsManager->get('enabled');
            $this->url = ($this->settingsManager->get('url') ?? '');
            $this->sharedKey = $this->settingsManager->getSerialized('sharedKey') ?? [];
            $this->supportedAlgorithms = ($this->settingsManager->get('supportedAlgorithms') ?? []);
            $this->idAttribute = ($this->settingsManager->get('idAttribute') ?? '');
            $this->leeway = $this->settingsManager->get('leeway') ?? 0;
            $this->allowedIPs = $this->settingsManager->get('allowedIPs') ?? [];
            $this->autoLogin = (bool)$this->settingsManager->get('autoLogin');
        }
    }

But the following error then happens for me;

yii\base\ErrorException: Undefined property: humhub\components\Application::$authClientCollection in /home/greenmet/public_html/protected/modules/jwt-sso/Module.php:53

@yurabakhtin
Copy link
Contributor

But the following error then happens for me;

yii\base\ErrorException: Undefined property: humhub\components\Application::$authClientCollection in /home/greenmet/public_html/protected/modules/jwt-sso/Module.php:53

@ArchBlood I think you should either define the property authClientCollection somehow there, or run the code only when if (isset(Yii::$app->authClientCollection)) or if (Yii::$app->authClientCollection instanceof humhub\modules\user\authclient\Collection) .

@ArchBlood
Copy link
Author

But the following error then happens for me;

yii\base\ErrorException: Undefined property: humhub\components\Application::$authClientCollection in /home/greenmet/public_html/protected/modules/jwt-sso/Module.php:53

@ArchBlood I think you should either define the property authClientCollection somehow there, or run the code only when if (isset(Yii::$app->authClientCollection)) or if (Yii::$app->authClientCollection instanceof humhub\modules\user\authclient\Collection) .

Seems like neither of these options work correctly either, I set like this and the login page is now viewable, but I'm not sure this is the correct way of doing this;

        if (!isset(Yii::$app->authClientCollection)) {
            $jwtAuth = Yii::$app->authClientCollection->getClient('jwt');

            if ($jwtAuth->checkIPAccess()) {
                if ($jwtAuth->autoLogin && $event->action->id === 'login' && empty(Yii::$app->request->get('noJwt'))) {
                    if ($event->isValid) {
                        $event->isValid = false;
                        return $jwtAuth->redirectToBroker();
                    }
                }
            } else {
                // Not allowed, remove authClient
                Yii::$app->authClientCollection->removeClient('jwt');
            }
        }

@ArchBlood ArchBlood marked this pull request as ready for review January 10, 2024 08:51
@yurabakhtin
Copy link
Contributor

Seems like neither of these options work correctly either, I set like this and the login page is now viewable, but I'm not sure this is the correct way of doing this;

@ArchBlood I didn't run/test your code but for me it looks incorrectly when you do if (!isset(Yii::$app->authClientCollection)) { and then try access to the undefined Yii::$app->authClientCollection.

Why don't you use the condition as I suggested if (isset(Yii::$app->authClientCollection)) {?

Really I think you should use instead of old code:

  • if (Yii::$app->authClientCollection->hasClient('jwt')) {

new code like:

  • if (isset(Yii::$app->authClientCollection) && Yii::$app->authClientCollection->hasClient('jwt')) {

or:

  • if (Yii::$app->authClientCollection instanceof humhub\modules\user\authclient\Collection && Yii::$app->authClientCollection->hasClient('jwt')) {

@ArchBlood
Copy link
Author

Seems like neither of these options work correctly either, I set like this and the login page is now viewable, but I'm not sure this is the correct way of doing this;

@ArchBlood I didn't run/test your code but for me it looks incorrectly when you do if (!isset(Yii::$app->authClientCollection)) { and then try access to the undefined Yii::$app->authClientCollection.

Why don't you use the condition as I suggested if (isset(Yii::$app->authClientCollection)) {?

Really I think you should use instead of old code:

  • if (Yii::$app->authClientCollection->hasClient('jwt')) {

new code like:

  • if (isset(Yii::$app->authClientCollection) && Yii::$app->authClientCollection->hasClient('jwt')) {

or:

  • if (Yii::$app->authClientCollection instanceof humhub\modules\user\authclient\Collection && Yii::$app->authClientCollection->hasClient('jwt')) {

Because these throw the following error, using the current code or if (!isset(Yii::$app->authClientCollection) && Yii::$app->authClientCollection->hasClient('jwt')) { doesn't;

yii\base\ErrorException: Undefined property: humhub\components\Application::$authClientCollection in /home/USER/public_html/protected/modules/jwt-sso/Module.php:68
Stack trace:
#0 /home/USER/public_html/protected/modules/jwt-sso/Module.php(68): yii\base\ErrorHandler->handleError()
#1 [internal function]: humhub\modules\sso\jwt\Module::onAuthClientCollectionInit()
#2 /home/USER/public_html/protected/vendor/yiisoft/yii2/base/Event.php(312): call_user_func()
#3 /home/USER/public_html/protected/vendor/yiisoft/yii2/base/Component.php(642): yii\base\Event::trigger()
#4 /home/USER/public_html/protected/humhub/modules/user/authclient/Collection.php(48): yii\base\Component->trigger()
#5 /home/USER/public_html/protected/vendor/yiisoft/yii2/base/Component.php(180): humhub\modules\user\authclient\Collection->setClients()
#6 /home/USER/public_html/protected/vendor/yiisoft/yii2/BaseYii.php(558): yii\base\Component->__set()
#7 /home/USER/public_html/protected/vendor/yiisoft/yii2/base/BaseObject.php(107): yii\BaseYii::configure()
#8 [internal function]: yii\base\BaseObject->__construct()
#9 /home/USER/public_html/protected/vendor/yiisoft/yii2/di/Container.php(419): ReflectionClass->newInstanceArgs()
#10 /home/USER/public_html/protected/vendor/yiisoft/yii2/di/Container.php(170): yii\di\Container->build()
#11 /home/USER/public_html/protected/vendor/yiisoft/yii2/BaseYii.php(365): yii\di\Container->get()
#12 /home/USER/public_html/protected/vendor/yiisoft/yii2/di/ServiceLocator.php(137): yii\BaseYii::createObject()
#13 /home/USER/public_html/protected/vendor/yiisoft/yii2/base/Module.php(766): yii\di\ServiceLocator->get()
#14 /home/USER/public_html/protected/vendor/yiisoft/yii2/di/ServiceLocator.php(74): yii\base\Module->get()
#15 /home/USER/public_html/protected/modules/jwt-sso/Module.php(68): yii\di\ServiceLocator->__get()
#16 [internal function]: humhub\modules\sso\jwt\Module::onAuthClientCollectionInit()
#17 /home/USER/public_html/protected/vendor/yiisoft/yii2/base/Event.php(312): call_user_func()
#18 /home/USER/public_html/protected/vendor/yiisoft/yii2/base/Component.php(642): yii\base\Event::trigger()
#19 /home/USER/public_html/protected/vendor/yiisoft/yii2/base/Controller.php(297): yii\base\Component->trigger()
#20 /home/USER/public_html/protected/vendor/yiisoft/yii2/web/Controller.php(219): yii\base\Controller->beforeAction()
#21 /home/USER/public_html/protected/humhub/components/Controller.php(210): yii\web\Controller->beforeAction()
#22 /home/USER/public_html/protected/humhub/modules/user/controllers/AuthController.php(94): humhub\components\Controller->beforeAction()
#23 /home/USER/public_html/protected/vendor/yiisoft/yii2/base/Controller.php(176): humhub\modules\user\controllers\AuthController->beforeAction()
#24 /home/USER/public_html/protected/vendor/yiisoft/yii2/base/Module.php(552): yii\base\Controller->runAction()
#25 /home/USER/public_html/protected/vendor/yiisoft/yii2/web/Application.php(103): yii\base\Module->runAction()
#26 /home/USER/public_html/protected/vendor/yiisoft/yii2/base/Application.php(384): yii\web\Application->handleRequest()
#27 /home/USER/public_html/index.php(25): yii\base\Application->run()
#28 {main}

@yurabakhtin
Copy link
Contributor

Because these throw the following error, using the current code or if (!isset(Yii::$app->authClientCollection) && Yii::$app->authClientCollection->hasClient('jwt')) { doesn't;

@ArchBlood You write here !isset(...) but I advised to use isset(...).

@ArchBlood
Copy link
Author

Because these throw the following error, using the current code or if (!isset(Yii::$app->authClientCollection) && Yii::$app->authClientCollection->hasClient('jwt')) { doesn't;

@ArchBlood You write here !isset(...) but I advised to use isset(...).

I can switch it to that, but the error will continue to happen, should I apply error handling as well?

@ArchBlood
Copy link
Author

ArchBlood commented Jan 10, 2024

After testing the following now works, but still throws Error occurred: Undefined property: humhub\components\Application::$authClientCollection just allows access to login even if it errors;

    public static function onAuthClientCollectionInit($event)
    {
        try {
            if (!Yii::$app->user->isGuest) {
                return;
            }

            /** @var Collection $authClientCollection */
            $authClientCollection = $event->sender;

            $config = Configuration::getInstance();

            if (!empty($config->enabled)) {
                $authClientCollection->setClient('jwt', [
                    'class' => authclient\JWT::class,
                    'url' => $config->url,
                    'sharedKey' => $config->sharedKey,
                    'supportedAlgorithms' => $config->supportedAlgorithms,
                    'idAttribute' => $config->idAttribute,
                    'leeway' => $config->leeway,
                    'allowedIPs' => $config->allowedIPs
                ]);
            }

            if (isset(Yii::$app->authClientCollection) && Yii::$app->authClientCollection->hasClient('jwt')) {
                $jwtAuth = Yii::$app->authClientCollection->getClient('jwt');

                if ($jwtAuth->checkIPAccess()) {
                    if ($jwtAuth->autoLogin && $event->action->id === 'login' && empty(Yii::$app->request->get('noJwt'))) {
                        if ($event->isValid) {
                            $event->isValid = false;
                            return $jwtAuth->redirectToBroker();
                        }
                    }
                } else {
                    Yii::$app->authClientCollection->removeClient('jwt');
                }
            }
        } catch (\Exception $e) {
            // Log or handle the exception as needed
            Yii::error('Error occurred: ' . $e->getMessage());
        }
    }

@yurabakhtin
Copy link
Contributor

After testing the following now works, but still throws Error occurred: Undefined property: humhub\components\Application::$authClientCollection just allows access to login even if it errors;

@ArchBlood Maybe you should compare the $event->sender is really object of Collection with code like:

if (!($event->sender instanceof Collection)) {
    return;
}

because I see the module config calls the method onAuthClientCollectionInit on two events:

[Collection::class, Collection::EVENT_AFTER_CLIENTS_SET, ['humhub\modules\sso\jwt\Module', 'onAuthClientCollectionInit']],
[AuthController::class, AuthController::EVENT_BEFORE_ACTION, ['humhub\modules\sso\jwt\Module', 'onAuthClientCollectionInit']],

I guess the event AuthController::EVENT_BEFORE_ACTION doesn't have the $event->sender as Collection, I think there we have $event->sender instanceof AuthController, please check, and probably you should remove the second config line completely, but I am not sure because I didn't test this code deeply.

I just see you added the first config line for Collection::EVENT_AFTER_CLIENTS_SET and then added the code with $authClientCollection = $event->sender; there but I think we should use a separate callback method per event, also it would be better to keep more correct names for the callback methods and we prefer to keep them all in separate file Events.php instead of Module.php, I mean the config should looks like this:

[Collection::class, Collection::EVENT_AFTER_CLIENTS_SET, ['humhub\modules\sso\jwt\Events', 'onCollectionAfterClientsSet']],
[AuthController::class, AuthController::EVENT_BEFORE_ACTION, ['humhub\modules\sso\jwt\Events', 'onAuthControllerBeforeAction']],

then you should move the code(or part of the code) from Module::onAuthClientCollectionInit() to Events::onCollectionAfterClientsSet(), and then decide what to do with the second event AuthController::EVENT_BEFORE_ACTION, you should either delete it completely or create new method Events::onAuthControllerBeforeAction()` and decide what code should be there, maybe some part of the code should be kept there.

Thanks.

@ArchBlood
Copy link
Author

After testing the following now works, but still throws Error occurred: Undefined property: humhub\components\Application::$authClientCollection just allows access to login even if it errors;

@ArchBlood Maybe you should compare the $event->sender is really object of Collection with code like:

if (!($event->sender instanceof Collection)) {
    return;
}

because I see the module config calls the method onAuthClientCollectionInit on two events:

[Collection::class, Collection::EVENT_AFTER_CLIENTS_SET, ['humhub\modules\sso\jwt\Module', 'onAuthClientCollectionInit']],
[AuthController::class, AuthController::EVENT_BEFORE_ACTION, ['humhub\modules\sso\jwt\Module', 'onAuthClientCollectionInit']],

I guess the event AuthController::EVENT_BEFORE_ACTION doesn't have the $event->sender as Collection, I think there we have $event->sender instanceof AuthController, please check, and probably you should remove the second config line completely, but I am not sure because I didn't test this code deeply.

I just see you added the first config line for Collection::EVENT_AFTER_CLIENTS_SET and then added the code with $authClientCollection = $event->sender; there but I think we should use a separate callback method per event, also it would be better to keep more correct names for the callback methods and we prefer to keep them all in separate file Events.php instead of Module.php, I mean the config should looks like this:

[Collection::class, Collection::EVENT_AFTER_CLIENTS_SET, ['humhub\modules\sso\jwt\Events', 'onCollectionAfterClientsSet']],
[AuthController::class, AuthController::EVENT_BEFORE_ACTION, ['humhub\modules\sso\jwt\Events', 'onAuthControllerBeforeAction']],

then you should move the code(or part of the code) from Module::onAuthClientCollectionInit() to Events::onCollectionAfterClientsSet(), and then decide what to do with the second event AuthController::EVENT_BEFORE_ACTION, you should either delete it completely or create new method Events::onAuthControllerBeforeAction()` and decide what code should be there, maybe some part of the code should be kept there.

Thanks.

Yes, you are correct, but in all honesty the whole onAuthClientCollectionInit() should be in the Events.php not Module.php, once I have the time later today to make the changes I'll run some tests then update the code here!

  1. https://github.com/humhub/jwt-sso/blob/master/Module.php#L26
  2. https://github.com/humhub-contrib/auth-twitter/blob/master/Events.php#L16

@ArchBlood
Copy link
Author

Now no errors happen at all! 😄

@ArchBlood
Copy link
Author

All that's needed now is live testing, which I can't current do as I have no JWT instances setup.

@ArchBlood
Copy link
Author

If anyone can run some tests for this it would be nice, otherwise I believe that everything looks to be working as intended. 🤔

@ArchBlood ArchBlood mentioned this pull request Jan 30, 2024
@ArchBlood
Copy link
Author

ArchBlood commented Jul 28, 2024

I've updated both the JWT init() & Events to fix some possible redirection errors, while also adding some error handling where needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Configuration Settings
2 participants