Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions doc/Admin Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,15 @@ Interactive admin configuration:
occ twofactorauth:gateway:configure sms
```

### Plivo
URL: https://www.plivo.com
Stability: Experimental

Use the HTTPS service provided by plivo.com for sending SMS.

Interactive admin configuration:
```bash
occ twofactorauth:gateway:configure sms
```

[User Documentation]: https://nextcloud-twofactor-gateway.readthedocs.io/en/latest/User%20Documentation/
43 changes: 41 additions & 2 deletions lib/Command/Configure.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\Sms77IoConfig;
use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\OvhConfig;
use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\WebSmsConfig;
use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\PlivoConfig;
use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\PuzzelSMSConfig;
use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\HuaweiE3531Config;
use OCA\TwoFactorGateway\Service\Gateway\SMS\Provider\SpryngSMSConfig;
Expand Down Expand Up @@ -108,8 +109,23 @@ private function configureSignal(InputInterface $input, OutputInterface $output)

private function configureSms(InputInterface $input, OutputInterface $output) {
$helper = $this->getHelper('question');

$providerQuestion = new Question('Please choose a SMS provider (websms, playsms, clockworksms, puzzelsms, ecallsms, voipms, huawei_e3531, spryng, sms77io, ovh, clickatellcentral, clicksend): ', 'websms');
$providerArray = ['websms',
'playsms',
'clockworksms',
'puzzelsms',
'ecallsms',
'voipms',
'huawei_e3531',
'spryng',
'sms77io',
'ovh',
'clickatellcentral',
'clicksend',
'plivo'
];
sort($providerArray,SORT_STRING);
$strOfProviders = implode(',', $providerArray);
$providerQuestion = new Question("Please choose a SMS provider ($strOfProviders): ", 'websms');
$provider = $helper->ask($input, $output, $providerQuestion);

/** @var SMSConfig $config */
Expand Down Expand Up @@ -313,6 +329,29 @@ private function configureSms(InputInterface $input, OutputInterface $output) {
$providerConfig->setUser($username);
$providerConfig->setApiKey($apiKey);

break;
case 'plivo':
$config->setProvider($provider);
/** @var PlivoConfig $providerConfig */
$providerConfig = $config->getProvider()->getConfig();

$authIdQuestion = new Question('Please enter your plivo authentication id (Auth ID): ');
$authId = $helper->ask($input, $output, $authIdQuestion);

$authTokenQuestion = new Question('Please enter your plivo authentication token (Auth Token): ');
$authToken = $helper->ask($input, $output, $authTokenQuestion);

$srcNumberQuestion = new Question("Please enter your plivo phone number (in E.164 format '+12345678901'): ");
$srcNumber = $helper->ask($input, $output, $srcNumberQuestion);

$callbackUrlQuestion = new Question('Please enter your plivo callback url: ');
$callbackUrl = $helper->ask($input, $output, $callbackUrlQuestion);

$providerConfig->setValue(PlivoConfig::AUTH_ID_KEY,$authId);
$providerConfig->setValue(PlivoConfig::AUTH_TOKEN_KEY, $authToken);
$providerConfig->setValue(PlivoConfig::CALLBACK_URL, $callbackUrl);
$providerConfig->setValue(PlivoConfig::SRC_NUMBER_KEY, $srcNumber);

break;

default:
Expand Down
91 changes: 91 additions & 0 deletions lib/Service/Gateway/SMS/Provider/Plivo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<?php

declare(strict_types=1);

/**
* @author Chris Jenkins <chris.j@guruinventions.com>
*
* Plivo - Config for Two-factor Gateway for Plivo
*
* 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\SMS\Provider;

use Exception;
use OCA\TwoFactorGateway\Exception\SmsTransmissionException;
use OCP\Http\Client\IClient;
use OCP\Http\Client\IClientService;
use \OCP\ILogger;

class Plivo implements IProvider {
public const PROVIDER_ID = 'plivo';

/** @var IClient */
private $client;

/** @var PlivoConfig */
private $config;

private $logger;

public function __construct(IClientService $clientService,
PlivoConfig $config, ILogger $logger) {
$this->client = $clientService->newClient();
$this->config = $config;
$this->logger = $logger;
}

/**
* @param string $identifier
* @param string $message
*
* @throws SmsTransmissionException
*/
public function send(string $identifier, string $message) {
$config = $this->getConfig();
$authToken = $config->getValue($config::AUTH_TOKEN_KEY);
$authID = $config->getValue($config::AUTH_ID_KEY);
$srcNumber = $config->getValue($config::SRC_NUMBER_KEY);

$apiParams = [
'body' => json_encode([
'dst' => $identifier,
'src' => $srcNumber,
'text' => $message
],JSON_FORCE_OBJECT),
'headers' => [
'Content-Type' => "application/json",
'Authorization' => "Basic " . base64_encode($authID.':'.$authToken)
]
];

try {
$this->logger->debug("api call: https://api.plivo.com/v1/Account/$authID/Message/" .print_r($apiParams,true));
$this->client->post("https://api.plivo.com/v1/Account/$authID/Message/", $apiParams);
} catch (Exception $ex) {
$this->logger->logException($ex, [
'message' => 'Could not send Plivo message: ' . $ex->getMessage(),
]);
throw new SmsTransmissionException();
}
}

/**
* @return PlivoConfig
*/
public function getConfig(): IProviderConfig {
return $this->config;
}
}
76 changes: 76 additions & 0 deletions lib/Service/Gateway/SMS/Provider/PlivoConfig.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

declare(strict_types=1);

/**
* @author Chris Jenkins <chris.j@guruinventions.com>
*
* Plivo - Config for Two-factor Gateway for Plivo
*
* 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\SMS\Provider;

use function array_intersect;
use OCA\TwoFactorGateway\AppInfo\Application;
use OCA\TwoFactorGateway\Exception\ConfigurationException;
use OCP\IConfig;

class PlivoConfig implements IProviderConfig {

/** @var IConfig */
private $config;

public const AUTH_ID_KEY = 'plivo_auth_id';
public const AUTH_TOKEN_KEY = 'plivo_auth_token';
public const SRC_NUMBER_KEY = 'plivo_src_number';

private const EXPECTED_KEYS = [
self::AUTH_ID_KEY,
self::AUTH_TOKEN_KEY,
self::SRC_NUMBER_KEY
];

public function __construct(IConfig $config) {
$this->config = $config;
}

private function getInternalValue(string $key): string {
$val = $this->config->getAppValue(Application::APP_NAME, $key, null);
if (is_null($val)) {
throw new ConfigurationException();
}
return $val;
}

public function getValue(string $key): string {
return $this->getInternalValue($key);
}

public function setValue(string $key, string $value) {
$this->config->setAppValue(Application::APP_NAME, $key, $value);
}

public function isComplete(): bool {
$set = $this->config->getAppKeys(Application::APP_NAME);
return count(array_intersect($set,self::EXPECTED_KEYS)) === count(self::EXPECTED_KEYS);
}

public function remove() {
foreach (self::EXPECTED_KEYS as $key) {
$this->config->deleteAppValue(Application::APP_NAME, $key);
}
}
}
2 changes: 2 additions & 0 deletions lib/Service/Gateway/SMS/Provider/ProviderFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public function getProvider(string $id): IProvider {
return $this->container->query(ClickatellCentral::class);
case ClickSend::PROVIDER_ID:
return $this->container->query(ClickSend::class);
case Plivo::PROVIDER_ID:
return $this->container->query(Plivo::class);
default:
throw new InvalidSmsProviderException("Provider <$id> does not exist");
}
Expand Down