Completed
Push — master ( 151189...cefe09 )
by Vitor
27s queued 22s
created

SetupService::getChallengePhoneNumber()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 8
ccs 0
cts 6
cp 0
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * SPDX-FileCopyrightText: 2024 Christoph Wurst <[email protected]>
7
 * SPDX-License-Identifier: AGPL-3.0-or-later
8
 */
9
10
namespace OCA\TwoFactorGateway\Service;
11
12
use Exception;
13
use OCA\TwoFactorGateway\Exception\IdentifierMissingException;
14
use OCA\TwoFactorGateway\Exception\InvalidProviderException;
15
use OCA\TwoFactorGateway\Exception\MessageTransmissionException;
16
use OCA\TwoFactorGateway\Exception\VerificationException;
17
use OCA\TwoFactorGateway\Provider\Factory as ProviderFactory;
18
use OCA\TwoFactorGateway\Provider\Gateway\Factory as GatewayFactory;
19
use OCA\TwoFactorGateway\Provider\State;
20
use OCP\Authentication\TwoFactorAuth\IRegistry;
21
use OCP\IL10N;
22
use OCP\IUser;
23
use OCP\Security\ISecureRandom;
24
25
class SetupService {
26 5
	public function __construct(
27
		private StateStorage $stateStorage,
28
		private GatewayFactory $gatewayFactory,
29
		private ProviderFactory $providerFactory,
30
		private ISecureRandom $random,
31
		private IRegistry $providerRegistry,
32
		private IL10N $l10n,
33
	) {
34 5
	}
35
36
	public function getState(IUser $user, string $gatewayName): State {
37
		return $this->stateStorage->get($user, $gatewayName);
38
	}
39
40
	/**
41
	 * @throws IdentifierMissingException
42
	 */
43
	public function getChallengePhoneNumber(IUser $user, string $gatewayName): string {
44
		$state = $this->stateStorage->get($user, $gatewayName);
45
		$identifier = $state->getIdentifier();
46
		if (is_null($identifier)) {
47
			throw new IdentifierMissingException("verified identifier for $gatewayName is missing");
48
		}
49
50
		return $identifier;
51
	}
52
53
	/**
54
	 * Send out confirmation message and save current identifier in user settings
55
	 *
56
	 * @throws VerificationException
57
	 */
58 2
	public function startSetup(IUser $user, string $gatewayName, string $identifier): State {
59 2
		$verificationNumber = $this->random->generate(6, ISecureRandom::CHAR_DIGITS);
60 2
		$gateway = $this->gatewayFactory->get($gatewayName);
61
		try {
62 2
			$gateway->send(
63 2
				$identifier,
64 2
				$this->l10n->t('%s is your verification code.', [$verificationNumber]),
65 2
				['code' => $verificationNumber],
66 2
			);
67 1
		} catch (MessageTransmissionException $ex) {
68
			throw new VerificationException($ex->getMessage(), $ex->getCode(), $ex);
69
		}
70
71 1
		return $this->stateStorage->persist(
72 1
			State::verifying($user, $gatewayName, $identifier, $verificationNumber)
73 1
		);
74
	}
75
76 3
	public function finishSetup(IUser $user, string $gatewayName, string $token): State {
77 3
		$state = $this->stateStorage->get($user, $gatewayName);
78 3
		if (is_null($state->getVerificationCode())) {
79 1
			throw new VerificationException($this->l10n->t('no verification code set'));
80
		}
81
82 2
		if ($state->getVerificationCode() !== $token) {
83 1
			throw new VerificationException($this->l10n->t('verification token mismatch'));
84
		}
85
86
		try {
87 1
			$provider = $this->providerFactory->get($gatewayName);
88
		} catch (InvalidProviderException) {
89
			throw new VerificationException('Invalid provider');
90
		}
91 1
		$this->providerRegistry->enableProviderFor($provider, $user);
92
93
		try {
94 1
			return $this->stateStorage->persist(
95 1
				$state->verify()
96 1
			);
97
		} catch (Exception $e) {
98
			throw new VerificationException($e->getMessage());
99
		}
100
	}
101
102
	public function disable(IUser $user, string $gatewayName): State {
103
		try {
104
			$provider = $this->providerFactory->get($gatewayName);
105
		} catch (InvalidProviderException) {
106
			throw new VerificationException('Invalid provider');
107
		}
108
		$this->providerRegistry->enableProviderFor($provider, $user);
109
		$this->providerRegistry->disableProviderFor($provider, $user);
110
111
		try {
112
			return $this->stateStorage->persist(
113
				State::disabled($user, $gatewayName)
114
			);
115
		} catch (Exception $e) {
116
			throw new VerificationException($e->getMessage());
117
		}
118
	}
119
}
120