-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Stateful 2fa providers #9632
Stateful 2fa providers #9632
Conversation
Codecov Report
@@ Coverage Diff @@
## master #9632 +/- ##
============================================
- Coverage 52.1% 52.09% -0.01%
- Complexity 25910 25949 +39
============================================
Files 1642 1648 +6
Lines 95721 95862 +141
Branches 1289 1289
============================================
+ Hits 49871 49943 +72
- Misses 45850 45919 +69
|
a3bd376
to
7c27db9
Compare
7c27db9
to
35b8532
Compare
This is ready for review now. Steps to test:
Before: Now: |
|
->andWhere($qb->expr()->eq('enabled', $qb->createNamedParameter(0))); | ||
$res = $q->execute(); | ||
$cnt = $res->rowCount(); | ||
$this->assertSame(1, $cnt); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some weird reason the query returns 0
rows here. I cannot find out why that is the case. If I attach a debugger an step through the code I see that the ->persist
call inserts one row.
@rullzer did I use the query builder incorrectly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rowcount is the number of rows affected by insert/update/delete
Either do 'fetchAll' and count on that. Or use the count function in the query. Both should work just fine here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should have read the method docs. Makes sense, updated my code and tests seem to pass locally. Thanks a lot!
version.php
Outdated
@@ -29,7 +29,7 @@ | |||
// between betas, final and RCs. This is _not_ the public version number. Reset minor/patchlevel | |||
// when updating major/minor version number. | |||
|
|||
$OC_Version = array(14, 0, 0, 4); | |||
$OC_Version = array(14, 0, 0, 5); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs to be changed again, because another PR with the same change got merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep #9485 (comment)
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` | ||
* @param array $options | ||
*/ | ||
public function preSchemaChange(IOutput $output, Closure $schemaClosure, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` | ||
* @param array $options | ||
*/ | ||
public function postSchemaChange(IOutput $output, Closure $schemaClosure, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
->andWhere($qb->expr()->eq('enabled', $qb->createNamedParameter(0))); | ||
$res = $q->execute(); | ||
$cnt = $res->rowCount(); | ||
$this->assertSame(1, $cnt); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rowcount is the number of rows affected by insert/update/delete
Either do 'fetchAll' and count on that. Or use the count function in the query. Both should work just fine here.
Very cool stuff. I need to test it properly but code makes a lot of sense |
Let's see if CI likes the current state and if so, I'll squash my commits one more time. |
This adds persistence to the Nextcloud server 2FA logic so that the server knows which 2FA providers are enabled for a specific user at any time, even when the provider is not available. The `IStatefulProvider` interface was added as tagging interface for providers that are compatible with this new API. Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
f341134
to
13d93f5
Compare
And now? xD |
Squashed, rebased and CI is happy. Time to review :) Will fix the 2fa providers soonish so that they propagate their state automatically. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool stuff!!!
@@ -0,0 +1,88 @@ | |||
<?php | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
strict
* @param string $appId | ||
*/ | ||
protected function loadTwoFactorApp(string $appId) { | ||
if (!OC_App::isAppLoaded($appId)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we use the appmanager here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neither the interface, nor the implementation provide methods to load an app.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #8505
@@ -0,0 +1,71 @@ | |||
<?php | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
strict
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
@@ -1,6 +1,11 @@ | |||
<div class="warning"> | |||
<h2 class="two-factor-header"><?php p($l->t('Two-factor authentication')) ?></h2> | |||
<p><?php p($l->t('Enhanced security is enabled for your account. Please authenticate using a second factor.')) ?></p> | |||
<?php if ($_['providerMissing']): ?> | |||
<p> | |||
<strong><?php p($l->t('Could not load at least one of your enabled two-factor auth methods. Please contact your admin.')) ?></strong> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to add an setup check for this as well? Just iterate over the table and list them for the admin?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like querying a set of generally enabled providers and checking if they can be loaded? Sounds reasonable.
Edit: I'll create a ticket for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-> #9985
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
The one failing acceptance tests looks unrelated to this change. |
|
||
namespace OC\Core\Command\TwoFactorAuth; | ||
|
||
use OC\Core\Command\Base; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PHP Fatal error: Cannot use OC\Core\Command\Base as Base because the name is already in use in /drone/src/github.com/nextcloud/server/core/Command/TwoFactorAuth/State.php on line 29
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #10023
- Admins can enable or disable 2FA for all users, this change give the possibility to be "statefull" in other word we have to register enable/disable state for all users in IRegistry during plugin configuration (all user IRegistry will be populated at first config) - Add type to IProvider implemented classes
This change makes two-factor providers and their association with users (whether the provider is enabled or not) stateful as in that we don't actually require the provider to be loaded when we want to check if a user uses 2FA. This greatly improves performance as we don't have to read from the file system and parse the
info.xml
file.To do:
IRegistry
to propagate their enabled/disabled stateProper handling of the backup codes app (auto-enable when other providers get enabled? auto-disable when all other providers get disabled?)won't change that for now and keep the existing logic (app has to be configured by user).cc @rullzer