Passed
Pull Request — master (#686)
by Vitor
04:21
created

Gateway::createSettings()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 22
dl 0
loc 27
ccs 0
cts 25
cp 0
rs 9.568
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * SPDX-FileCopyrightText: 2024 Rainer Dohmen <[email protected]>
7
 * SPDX-License-Identifier: AGPL-3.0-or-later
8
 */
9
10
namespace OCA\TwoFactorGateway\Provider\Channel\XMPP;
11
12
use OCA\TwoFactorGateway\Exception\MessageTransmissionException;
13
use OCA\TwoFactorGateway\Provider\FieldDefinition;
14
use OCA\TwoFactorGateway\Provider\Gateway\AGateway;
15
use OCA\TwoFactorGateway\Provider\Settings;
16
use OCP\IAppConfig;
17
use Psr\Log\LoggerInterface;
18
use Symfony\Component\Console\Helper\QuestionHelper;
19
use Symfony\Component\Console\Input\InputInterface;
20
use Symfony\Component\Console\Output\OutputInterface;
21
use Symfony\Component\Console\Question\Question;
22
23
/**
24
 * @method string getSender()
25
 * @method static setSender(string $sender)
26
 * @method string getPassword()
27
 * @method static setPassword(string $password)
28
 * @method string getServer()
29
 * @method static setServer(string $server)
30
 * @method string getUsername()
31
 * @method static setUsername(string $username)
32
 * @method string getMethod()
33
 * @method static setMethod(string $method)
34
 */
35
class Gateway extends AGateway {
36
	public function __construct(
37
		public IAppConfig $appConfig,
38
		private LoggerInterface $logger,
39
	) {
40
		parent::__construct($appConfig);
41
	}
42
43
	public function createSettings(): Settings {
44
		return new Settings(
45
			name: 'XMPP',
46
			instructions: <<<HTML
47
				<p>In order to receive authentication codes via XMPP, your XMPP Server must support http requests (ask your admin).</p>
48
				<p>Enter your JID (XMPP address) to receive your verification code below.</p>
49
				HTML,
50
			fields: [
51
				new FieldDefinition(
52
					field: 'sender',
53
					prompt: 'Please enter your sender XMPP-JID:',
54
				),
55
				new FieldDefinition(
56
					field: 'password',
57
					prompt: 'Please enter your sender XMPP password:',
58
				),
59
				new FieldDefinition(
60
					field: 'server',
61
					prompt: 'Please enter full path to access REST/HTTP API:',
62
				),
63
				new FieldDefinition(
64
					field: 'username',
65
					prompt: '',
66
				),
67
				new FieldDefinition(
68
					field: 'method',
69
					prompt: 'Please enter 1 or 2 for XMPP sending option:',
70
				),
71
			],
72
		);
73
	}
74
75
	#[\Override]
76
	public function send(string $identifier, string $message, array $extra = []): void {
77
		$this->logger->debug("sending xmpp message to $identifier, message: $message");
78
79
		$sender = $this->getSender();
80
		$password = $this->getPassword();
81
		$server = $this->getServer();
82
		$method = $this->getMethod();
83
		$user = $this->getUsername();
84
		$url = $server . $identifier;
85
86
		if ($method === '1') {
87
			$from = $user;
88
		}
89
		if ($method === '2') {
90
			$from = $sender;
91
		}
92
		$this->logger->debug("URL: $url, sender: $sender, method: $method");
93
94
		try {
95
			$ch = curl_init();
96
			curl_setopt($ch, CURLOPT_URL, $url);
97
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
98
			curl_setopt($ch, CURLOPT_POST, 1);
99
			curl_setopt($ch, CURLOPT_POSTFIELDS, $message);
100
			curl_setopt($ch, CURLOPT_USERPWD, $from . ':' . $password);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $from does not seem to be defined for all execution paths leading up to this point.
Loading history...
101
			curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: text/plain']);
102
			$result = curl_exec($ch);
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
103
			curl_close($ch);
104
			$this->logger->debug("XMPP message to $identifier sent");
105
		} catch (\Exception) {
106
			throw new MessageTransmissionException();
107
		}
108
	}
109
110
	#[\Override]
111
	public function cliConfigure(InputInterface $input, OutputInterface $output): int {
112
		$helper = new QuestionHelper();
113
		$settings = $this->getSettings();
114
		$fields = [];
115
		foreach ($settings->fields as $field) {
116
			$fields[$field->field] = $field;
117
		}
118
		$sender = '';
119
		while (empty($sender) or substr_count($sender, '@') !== 1) {
120
			$senderQuestion = new Question($fields['sender']->prompt . ' ');
121
			$sender = $helper->ask($input, $output, $senderQuestion);
122
			if (empty($sender)) {
123
				$output->writeln('XMPP-JID must not be empty!');
124
			} elseif (substr_count($sender, '@') !== 1) {
125
				$output->writeln('XMPP-JID not valid!');
126
			} else {
127
				$username = explode('@', $sender)[0];
128
			}
129
		}
130
		$output->writeln("Using $sender as XMPP-JID.\nUsing $username as username.");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $username does not seem to be defined for all execution paths leading up to this point.
Loading history...
131
		$password = '';
132
		while (empty($password)) {
133
			$passwordQuestion = new Question($fields['password']->prompt . ' ');
134
			$password = $helper->ask($input, $output, $passwordQuestion);
135
			if (empty($password)) {
136
				$output->writeln('Password must not be empty!');
137
			}
138
		}
139
		$output->writeln('Password accepted.');
140
		$server = '';
141
		while (empty($server)) {
142
			$serverQuestion = new Question($fields['server']->prompt . ' ');
143
			$server = $helper->ask($input, $output, $serverQuestion);
144
			if (empty($server)) {
145
				$output->writeln('API path must not be empty!');
146
			}
147
		}
148
		$output->writeln("Using $server as full URL to access REST/HTTP API.");
149
		$method = 0;
150
		while (intval($method) < 1 or intval($method) > 2) {
151
			echo $fields['method']->prompt . PHP_EOL;
152
			echo "(1) prosody with mod_rest\n";
153
			echo "(2) prosody with mod_post_msg\n";
154
			$methodQuestion = new Question('Your choice: ');
155
			$method = $helper->ask($input, $output, $methodQuestion);
156
		}
157
		if ($method === '1') {
158
			$output->writeln('Using prosody with mod_rest as XMPP sending option.');
159
		} elseif ($method === '2') {
160
			$output->writeln('Using prosody with mod_post_msg as XMPP sending option.');
161
		}
162
		$output->writeln('XMPP Admin Configuration finished.');
163
164
		$this->setSender($sender);
165
		$this->setPassword($password);
166
		$this->setServer($server);
167
		$this->setUsername($username);
168
		$this->setMethod($method);
169
		return 0;
170
	}
171
}
172