Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/twofactor_gateway.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Controller/SettingsController.php18
-rw-r--r--lib/Provider/AProvider.php11
-rw-r--r--lib/Provider/State.php13
-rw-r--r--lib/Service/Gateway/Factory.php64
-rw-r--r--lib/Service/Gateway/IGateway.php8
-rw-r--r--lib/Service/Gateway/SMS/Gateway.php10
-rw-r--r--lib/Service/Gateway/Signal/Gateway.php10
-rw-r--r--lib/Service/Gateway/Telegram/Gateway.php10
-rw-r--r--lib/Service/Gateway/TestGateway.php10
-rw-r--r--lib/Service/SetupService.php35
-rw-r--r--lib/Service/StateStorage.php78
11 files changed, 153 insertions, 114 deletions
diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php
index 94a5929..993db46 100644
--- a/lib/Controller/SettingsController.php
+++ b/lib/Controller/SettingsController.php
@@ -51,29 +51,31 @@ class SettingsController extends Controller {
/**
* @NoAdminRequired
*/
- public function getVerificationState(): JSONResponse {
+ public function getVerificationState(string $gateway): JSONResponse {
$user = $this->userSession->getUser();
if (is_null($user)) {
return new JSONResponse(null, Http::STATUS_BAD_REQUEST);
}
- return new JSONResponse($this->setup->getState($user));
+ return new JSONResponse($this->setup->getState($user, $gateway));
}
/**
* @NoAdminRequired
+ *
* @param string $identification
+ *
* @return JSONResponse
*/
- public function startVerification(string $identifier): JSONResponse {
+ public function startVerification(string $gateway, string $identifier): JSONResponse {
$user = $this->userSession->getUser();
if (is_null($user)) {
return new JSONResponse(null, Http::STATUS_BAD_REQUEST);
}
- $state = $this->setup->startSetup($user, $identifier);
+ $state = $this->setup->startSetup($user, $gateway, $identifier);
return new JSONResponse([
'phoneNumber' => $state->getIdentifier(),
@@ -83,7 +85,7 @@ class SettingsController extends Controller {
/**
* @NoAdminRequired
*/
- public function finishVerification(string $verificationCode): JSONResponse {
+ public function finishVerification(string $gateway, string $verificationCode): JSONResponse {
$user = $this->userSession->getUser();
if (is_null($user)) {
@@ -91,7 +93,7 @@ class SettingsController extends Controller {
}
try {
- $this->setup->finishSetup($user, $verificationCode);
+ $this->setup->finishSetup($user, $gateway, $verificationCode);
} catch (VerificationException $ex) {
return new JSONResponse(null, Http::STATUS_BAD_REQUEST);
}
@@ -102,14 +104,14 @@ class SettingsController extends Controller {
/**
* @NoAdminRequired
*/
- public function revokeVerification(): JSONResponse {
+ public function revokeVerification(string $gateway): JSONResponse {
$user = $this->userSession->getUser();
if (is_null($user)) {
return new JSONResponse(null, Http::STATUS_BAD_REQUEST);
}
- return new JSONResponse($this->setup->disable($user));
+ return new JSONResponse($this->setup->disable($user, $gateway));
}
}
diff --git a/lib/Provider/AProvider.php b/lib/Provider/AProvider.php
index a69cb75..628e63e 100644
--- a/lib/Provider/AProvider.php
+++ b/lib/Provider/AProvider.php
@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace OCA\TwoFactorGateway\Provider;
+use OCA\TwoFactorGateway\PhoneNumberMask;
use OCA\TwoFactorGateway\Service\Gateway\IGateway;
use OCA\TwoFactorGateway\Service\StateStorage;
use OCP\Authentication\TwoFactorAuth\IProvider;
@@ -40,7 +41,7 @@ abstract class AProvider implements IProvider {
const STATE_ENABLED = 3;
/** @var string */
- protected $gatewayId;
+ protected $gatewayName;
/** @var IGateway */
protected $gateway;
@@ -68,7 +69,7 @@ abstract class AProvider implements IProvider {
ISecureRandom $secureRandom,
IL10N $l10n) {
$this->gateway = $gateway;
- $this->gatewayId = $gatewayId;
+ $this->gatewayName = $gatewayId;
$this->stateStorage = $stateStorage;
$this->session = $session;
$this->secureRandom = $secureRandom;
@@ -79,7 +80,7 @@ abstract class AProvider implements IProvider {
* Get unique identifier of this 2FA provider
*/
public function getId(): string {
- return "gateway_$this->gatewayId";
+ return "gateway_$this->gatewayName";
}
private function getSecret(): string {
@@ -100,7 +101,7 @@ abstract class AProvider implements IProvider {
$secret = $this->getSecret();
try {
- $identifier = $this->stateStorage->get($user)->getIdentifier();
+ $identifier = $this->stateStorage->get($user, $this->gatewayName)->getIdentifier();
$this->gateway->send(
$user,
$identifier,
@@ -135,7 +136,7 @@ abstract class AProvider implements IProvider {
* Decides whether 2FA is enabled for the given user
*/
public function isTwoFactorAuthEnabledForUser(IUser $user): bool {
- return $this->stateStorage->get($user)->getState() === self::STATE_ENABLED;
+ return $this->stateStorage->get($user, $this->gatewayName)->getState() === self::STATE_ENABLED;
}
}
diff --git a/lib/Provider/State.php b/lib/Provider/State.php
index 58023a4..2b4ae0b 100644
--- a/lib/Provider/State.php
+++ b/lib/Provider/State.php
@@ -36,7 +36,7 @@ class State implements JsonSerializable {
/** @var int */
private $state;
- /** @var string|null */
+ /** @var string */
private $gatewayName;
/** @var string|null */
@@ -47,7 +47,7 @@ class State implements JsonSerializable {
public function __construct(IUser $user,
int $state,
- string $gatewayName = null,
+ string $gatewayName,
string $identifier = null,
string $verificationCode = null) {
$this->user = $user;
@@ -70,10 +70,11 @@ class State implements JsonSerializable {
);
}
- public static function disabled(IUser $user): State {
+ public static function disabled(IUser $user, string $gatewayName): State {
return new State(
$user,
- SmsProvider::STATE_DISABLED
+ SmsProvider::STATE_DISABLED,
+ $gatewayName
);
}
@@ -102,9 +103,9 @@ class State implements JsonSerializable {
}
/**
- * @return string|null
+ * @return string
*/
- public function getGatewayName() {
+ public function getGatewayName(): string {
return $this->gatewayName;
}
diff --git a/lib/Service/Gateway/Factory.php b/lib/Service/Gateway/Factory.php
new file mode 100644
index 0000000..a0dac01
--- /dev/null
+++ b/lib/Service/Gateway/Factory.php
@@ -0,0 +1,64 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * @author Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * Nextcloud - Two-factor Gateway
+ *
+ * This code is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License, version 3,
+ * along with this program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCA\TwoFactorGateway\Service\Gateway;
+
+use Exception;
+use OCA\TwoFactorGateway\Service\Gateway\Signal\Gateway as SignalGateway;
+use OCA\TwoFactorGateway\Service\Gateway\SMS\Gateway as SMSGateway;
+use OCA\TwoFactorGateway\Service\Gateway\Telegram\Gateway as TelegramGateway;
+
+class Factory {
+
+ /** @var SignalGateway */
+ private $signalGateway;
+
+ /** @var SMSGateway */
+ private $smsGateway;
+
+ /** @var TelegramGateway */
+ private $telegramGateway;
+
+ public function __construct(SignalGateway $signalGateway,
+ SMSGateway $smsGateway,
+ TelegramGateway $telegramGateway) {
+
+ $this->signalGateway = $signalGateway;
+ $this->smsGateway = $smsGateway;
+ $this->telegramGateway = $telegramGateway;
+ }
+
+ public function getGateway(string $name): IGateway {
+ switch ($name) {
+ case 'signal':
+ return $this->signalGateway;
+ case 'sms':
+ return $this->smsGateway;
+ case 'telegram':
+ return $this->telegramGateway;
+ default:
+ throw new Exception("Invalid gateway <$name>");
+ }
+ }
+
+}
diff --git a/lib/Service/Gateway/IGateway.php b/lib/Service/Gateway/IGateway.php
index da467c5..5d0d881 100644
--- a/lib/Service/Gateway/IGateway.php
+++ b/lib/Service/Gateway/IGateway.php
@@ -29,14 +29,6 @@ use OCP\IUser;
interface IGateway {
/**
- * Get a short description of this gateway's name so that users know how
- * their messages are delivered, e.g. "Telegram"
- *
- * @return string
- */
- public function getShortName(): string;
-
- /**
* Get the gateway-specific configuration
*
* @return IGatewayConfig
diff --git a/lib/Service/Gateway/SMS/Gateway.php b/lib/Service/Gateway/SMS/Gateway.php
index 53f985d..e91456f 100644
--- a/lib/Service/Gateway/SMS/Gateway.php
+++ b/lib/Service/Gateway/SMS/Gateway.php
@@ -49,16 +49,6 @@ class Gateway implements IGateway {
}
/**
- * Get a short description of this gateway's name so that users know how
- * their messages are delivered, e.g. "Telegram"
- *
- * @return string
- */
- public function getShortName(): string {
- return 'SMS';
- }
-
- /**
* Get the gateway-specific configuration
*
* @return GatewayConfig
diff --git a/lib/Service/Gateway/Signal/Gateway.php b/lib/Service/Gateway/Signal/Gateway.php
index c3c77f0..02d3f50 100644
--- a/lib/Service/Gateway/Signal/Gateway.php
+++ b/lib/Service/Gateway/Signal/Gateway.php
@@ -82,16 +82,6 @@ class Gateway implements IGateway {
}
/**
- * Get a short description of this gateway's name so that users know how
- * their messages are delivered, e.g. "Telegram"
- *
- * @return string
- */
- public function getShortName(): string {
- return 'Signal';
- }
-
- /**
* Get the gateway-specific configuration
*
* @return IGatewayConfig
diff --git a/lib/Service/Gateway/Telegram/Gateway.php b/lib/Service/Gateway/Telegram/Gateway.php
index f8295ad..d8b355c 100644
--- a/lib/Service/Gateway/Telegram/Gateway.php
+++ b/lib/Service/Gateway/Telegram/Gateway.php
@@ -96,16 +96,6 @@ class Gateway implements IGateway {
}
/**
- * Get a short description of this gateway's name so that users know how
- * their messages are delivered, e.g. "Telegram"
- *
- * @return string
- */
- public function getShortName(): string {
- return 'Telegram';
- }
-
- /**
* Get the gateway-specific configuration
*
* @return IGatewayConfig
diff --git a/lib/Service/Gateway/TestGateway.php b/lib/Service/Gateway/TestGateway.php
index 9cf7bb7..7d7f34c 100644
--- a/lib/Service/Gateway/TestGateway.php
+++ b/lib/Service/Gateway/TestGateway.php
@@ -42,16 +42,6 @@ class TestGateway implements IGateway {
}
/**
- * Get a short description of this gateway's name so that users know how
- * their messages are delivered, e.g. "Telegram"
- *
- * @return string
- */
- public function getShortName(): string {
- return 'Test';
- }
-
- /**
* @return string
*/
public function getProviderDescription(): string {
diff --git a/lib/Service/SetupService.php b/lib/Service/SetupService.php
index 15f5945..a5c7d51 100644
--- a/lib/Service/SetupService.php
+++ b/lib/Service/SetupService.php
@@ -29,9 +29,9 @@ use OCA\TwoFactorGateway\Exception\IdentifierMissingException;
use OCA\TwoFactorGateway\Exception\SmsTransmissionException;
use OCA\TwoFactorGateway\Exception\VerificationException;
use OCA\TwoFactorGateway\Exception\VerificationTransmissionException;
+use OCA\TwoFactorGateway\Service\Gateway\Factory as GatewayFactory;
use OCA\TwoFactorGateway\Provider\SmsProvider;
use OCA\TwoFactorGateway\Provider\State;
-use OCA\TwoFactorGateway\Service\Gateway\IGateway;
use OCP\Authentication\TwoFactorAuth\IRegistry;
use OCP\IUser;
use OCP\Security\ISecureRandom;
@@ -41,8 +41,8 @@ class SetupService {
/** @var StateStorage */
private $stateStorage;
- /** @var IGateway */
- private $smsService;
+ /** @var GatewayFactory */
+ private $gatewayFactory;
/** @var ISecureRandom */
private $random;
@@ -54,29 +54,29 @@ class SetupService {
private $providerRegistry;
public function __construct(StateStorage $stateStorage,
- IGateway $smsService,
+ GatewayFactory $gatewayFactory,
ISecureRandom $random,
SmsProvider $provider,
IRegistry $providerRegistry) {
$this->stateStorage = $stateStorage;
- $this->smsService = $smsService;
+ $this->gatewayFactory = $gatewayFactory;
$this->random = $random;
$this->provider = $provider;
$this->providerRegistry = $providerRegistry;
}
- public function getState(IUser $user): State {
- return $this->stateStorage->get($user);
+ public function getState(IUser $user, string $gatewayName): State {
+ return $this->stateStorage->get($user, $gatewayName);
}
/**
* @throws IdentifierMissingException
*/
- public function getChallengePhoneNumber(IUser $user): string {
- $state = $this->stateStorage->get($user);
+ public function getChallengePhoneNumber(IUser $user, string $gatewayName): string {
+ $state = $this->stateStorage->get($user, $gatewayName);
$identifier = $state->getIdentifier();
if (is_null($identifier)) {
- throw new IdentifierMissingException('verified identifier is missing');
+ throw new IdentifierMissingException("verified identifier for $gatewayName is missing");
}
return $identifier;
@@ -85,21 +85,22 @@ class SetupService {
/**
* Send out confirmation message and save current identifier in user settings
*/
- public function startSetup(IUser $user, string $identifier): State {
+ public function startSetup(IUser $user, string $gatewayName, string $identifier): State {
$verificationNumber = $this->random->generate(6, ISecureRandom::CHAR_DIGITS);
+ $gateway = $this->gatewayFactory->getGateway($gatewayName);
try {
- $this->smsService->send($user, $identifier, "$verificationNumber is your Nextcloud verification code.");
+ $gateway->send($user, $identifier, "$verificationNumber is your Nextcloud verification code.");
} catch (SmsTransmissionException $ex) {
throw new VerificationTransmissionException('could not send verification code');
}
return $this->stateStorage->persist(
- State::verifying($user, $this->smsService->getShortName(), $identifier, $verificationNumber)
+ State::verifying($user, $gatewayName, $identifier, $verificationNumber)
);
}
- public function finishSetup(IUser $user, string $token): State {
- $state = $this->stateStorage->get($user);
+ public function finishSetup(IUser $user, string $gatewayName, string $token): State {
+ $state = $this->stateStorage->get($user, $gatewayName);
if (is_null($state->getVerificationCode())) {
throw new Exception('no verification code set');
}
@@ -115,11 +116,11 @@ class SetupService {
);
}
- public function disable(IUser $user): State {
+ public function disable(IUser $user, string $gatewayName): State {
$this->providerRegistry->disableProviderFor($this->provider, $user);
return $this->stateStorage->persist(
- State::disabled($user)
+ State::disabled($user, $gatewayName)
);
}
diff --git a/lib/Service/StateStorage.php b/lib/Service/StateStorage.php
index 75e3f0f..10307d5 100644
--- a/lib/Service/StateStorage.php
+++ b/lib/Service/StateStorage.php
@@ -28,7 +28,6 @@ use Exception;
use OCA\TwoFactorGateway\AppInfo\Application;
use OCA\TwoFactorGateway\Provider\SmsProvider;
use OCA\TwoFactorGateway\Provider\State;
-use OCA\TwoFactorGateway\Service\Gateway\IGateway;
use OCP\IConfig;
use OCP\IUser;
@@ -41,10 +40,29 @@ class StateStorage {
$this->config = $config;
}
- public function get(IUser $user): State {
- $isVerified = $this->config->getUserValue($user->getUID(), Application::APP_NAME, 'verified', 'false') === 'true';
- $identifier = $this->config->getUserValue($user->getUID(), 'twofactor_gateway', 'identifier', null);
- $verificationCode = $this->config->getUserValue($user->getUID(), 'twofactor_gateway', 'verification_code', null);
+ private function buildConfigKey(string $gatewayName, string $key) {
+ return "twofactor_gateway_$gatewayName" . "_$key";
+ }
+
+ private function getUserValue(IUser $user, string $gatewayName, string $key, $default = '') {
+ $gatewayKey = $this->buildConfigKey($gatewayName, $key);
+ return $this->config->getUserValue($user->getUID(), Application::APP_NAME, $gatewayKey, $default);
+ }
+
+ private function setUserValue(IUser $user, string $gatewayName, string $key, $value) {
+ $gatewayKey = $this->buildConfigKey($gatewayName, $key);
+ $this->config->setUserValue($user->getUID(), Application::APP_NAME, $gatewayKey, $value);
+ }
+
+ private function deleteUserValue(IUser $user, string $gatewayName, string $key) {
+ $gatewayKey = $this->buildConfigKey($gatewayName, $key);
+ $this->config->deleteUserValue($user->getUID(), Application::APP_NAME, $gatewayKey);
+ }
+
+ public function get(IUser $user, string $gatewayName): State {
+ $isVerified = $this->getUserValue($user, $gatewayName, 'verified', 'false') === 'true';
+ $identifier = $this->getUserValue($user, $gatewayName, 'identifier', null);
+ $verificationCode = $this->getUserValue($user, $gatewayName, 'verification_code', null);
if ($isVerified) {
$state = SmsProvider::STATE_ENABLED;
@@ -57,7 +75,7 @@ class StateStorage {
return new State(
$user,
$state,
- '', // TODO: fix
+ $gatewayName,
$identifier,
$verificationCode
);
@@ -66,55 +84,55 @@ class StateStorage {
public function persist(State $state): State {
switch ($state->getState()) {
case SmsProvider::STATE_DISABLED:
- $this->config->deleteUserValue(
- $state->getUser()->getUID(),
- Application::APP_NAME,
+ $this->deleteUserValue(
+ $state->getUser(),
+ $state->getGatewayName(),
'verified'
);
- $this->config->deleteUserValue(
- $state->getUser()->getUID(),
- Application::APP_NAME,
+ $this->deleteUserValue(
+ $state->getUser(),
+ $state->getGatewayName(),
'verification_code'
);
break;
case SmsProvider::STATE_VERIFYING:
- $this->config->setUserValue(
- $state->getUser()->getUID(),
- Application::APP_NAME,
+ $this->setUserValue(
+ $state->getUser(),
+ $state->getGatewayName(),
'identifier',
$state->getIdentifier()
);
- $this->config->setUserValue(
- $state->getUser()->getUID(),
- Application::APP_NAME,
+ $this->setUserValue(
+ $state->getUser(),
+ $state->getGatewayName(),
'verification_code',
$state->getVerificationCode()
);
- $this->config->setUserValue(
- $state->getUser()->getUID(),
- Application::APP_NAME,
+ $this->setUserValue(
+ $state->getUser(),
+ $state->getGatewayName(),
'verified',
'false'
);
break;
case SmsProvider::STATE_ENABLED:
- $this->config->setUserValue(
- $state->getUser()->getUID(),
- Application::APP_NAME,
+ $this->setUserValue(
+ $state->getUser(),
+ $state->getGatewayName(),
'identifier',
$state->getIdentifier()
);
- $this->config->setUserValue(
- $state->getUser()->getUID(),
- Application::APP_NAME,
+ $this->setUserValue(
+ $state->getUser(),
+ $state->getGatewayName(),
'verification_code',
$state->getVerificationCode()
);
- $this->config->setUserValue(
- $state->getUser()->getUID(),
- Application::APP_NAME,
+ $this->setUserValue(
+ $state->getUser(),
+ $state->getGatewayName(),
'verified',
'true'
);