Complete email + SMS authentication

Also send an email when the email was changed
This commit is contained in:
Timothée Jaussoin 2020-04-20 17:23:58 +02:00
parent 8fcffd4ff8
commit f3ba51682f
16 changed files with 525 additions and 9 deletions

View file

@ -20,3 +20,16 @@ CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=cookie
SESSION_LIFETIME=120
MAIL_DRIVER=
MAIL_HOST=
MAIL_PORT=2525
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_FROM_ADDRESS=
MAIL_FROM_NAME=
OVH_APP_KEY=
OVH_APP_SECRET=
OVH_APP_ENDPOINT=ovh-eu
OVH_APP_CONSUMER_KEY=

View file

@ -5,10 +5,13 @@ namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Mail;
use App\Account;
use App\Rules\SIP;
use App\Helpers\Utils;
use App\Libraries\OvhSMS;
use App\Mail\PasswordAuthentication;
class AccountController extends Controller
{
@ -83,7 +86,7 @@ class AccountController extends Controller
$account->confirmation_key = Str::random($this->emailCodeSize);
$account->save();
// TODO send email
Mail::to($account)->send(new PasswordAuthentication($account));
return view('account.authenticate_email', [
'account' => $account
@ -125,7 +128,8 @@ class AccountController extends Controller
$account->confirmation_key = mt_rand(1000, 9999);
$account->save();
// TODO send SMS
$ovhSMS = new OvhSMS;
$ovhSMS->send($request->get('phone'), 'Your Linphone validation code is '.$account->confirmation_key);
return view('account.authenticate_phone', [
'account' => $account

View file

@ -3,6 +3,9 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Mail\ChangedEmail;
class AccountEmailController extends Controller
{
@ -15,16 +18,16 @@ class AccountEmailController extends Controller
public function update(Request $request)
{
// TODO exists doesn't already exists
$request->validate([
'email' => 'required|email',
'email_confirm' => 'required|same:email'
'email' => 'required|confirmed|email|unique:external.accounts,email',
]);
$account = $request->user();
$account->email = $request->get('email');
$account->save();
Mail::to($account)->send(new ChangedEmail());
return redirect()->route('account.index');
}
}

View file

@ -0,0 +1,62 @@
<?php
/*
Flexisip Account Manager is a set of tools to manage SIP accounts.
Copyright (C) 2019 Belledonne Communications SARL, All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
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
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace App\Libraries;
use App\Device;
use Ovh\Api;
class OvhSMS
{
private $_api;
private $_smsService;
public function __construct()
{
$this->_api = new Api(
config('ovh.app_key'),
config('ovh.app_secret'),
config('ovh.app_endpoint'),
config('ovh.app_consumer_key')
);
$smsServices = $this->_api->get('/sms/');
if (!empty($smsServices)) $this->_smsService = $smsServices[0];
}
public function send(string $to, string $message)
{
$content = (object) [
'charset' => 'UTF-8',
'class' => 'phoneDisplay',
'coding' => '7bit',
'message' => $message,
'noStopClause' => false,
'priority' => 'high',
'receivers' => [ $to ],
'senderForResponse' => true,
'validityPeriod' => 2880
];
$resultPostJob = $this->_api->post('/sms/'. $this->_smsService . '/jobs', $content);
// One credit removed
$smsJobs = $this->_api->get('/sms/'. $this->_smsService . '/jobs');
}
}

View file

@ -0,0 +1,21 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\Account;
class ChangedEmail extends Mailable
{
use Queueable, SerializesModels;
public function build()
{
return $this->view('mails.changed_email')
->text('mails.changed_email_text');
}
}

View file

@ -0,0 +1,41 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\Account;
class PasswordAuthentication extends Mailable
{
use Queueable, SerializesModels;
private $_account;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct(Account $account)
{
$this->_account = $account;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('mails.authentication')
->text('mails.authentication_text')
->with([
'link' => route('account.authenticate_email_confirm', [$this->_account->confirmation_key])
]);
}
}

View file

@ -13,6 +13,7 @@
"laravel/framework": "^6.2",
"laravel/tinker": "^2.0",
"laravelcollective/html": "^6.1",
"ovh/ovh": "^2.0",
"propaganistas/laravel-phone": "^4.2"
},
"require-dev": {

316
flexiapi/composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "1188abce9cc741a1318f4f7db580e86f",
"content-hash": "06757402a3ada8adde19707d8311f9f1",
"packages": [
{
"name": "dnoegel/php-xdg-base-dir",
@ -451,6 +451,195 @@
"description": "Locale functions required by libphonenumber-for-php",
"time": "2019-10-09T18:53:14+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "6.5.3",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/aab4ebd862aa7d04f01a4b51849d657db56d882e",
"reference": "aab4ebd862aa7d04f01a4b51849d657db56d882e",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.6.1",
"php": ">=5.5",
"symfony/polyfill-intl-idn": "^1.11"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
"psr/log": "^1.1"
},
"suggest": {
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.5-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle is a PHP HTTP client library",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
],
"time": "2020-04-18T10:38:46+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "v1.3.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"time": "2016-12-20T10:07:11+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "1.6.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "239400de7a173fe9901b9ac7c06497751f00727a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a",
"reference": "239400de7a173fe9901b9ac7c06497751f00727a",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0",
"ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"ext-zlib": "*",
"phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8"
},
"suggest": {
"zendframework/zend-httphandlerrunner": "Emit PSR-7 responses"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Schultze",
"homepage": "https://github.com/Tobion"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"psr-7",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2019-07-01T23:21:34+00:00"
},
{
"name": "laravel/framework",
"version": "v6.18.5",
@ -1236,6 +1425,41 @@
],
"time": "2019-11-29T22:36:02+00:00"
},
{
"name": "ovh/ovh",
"version": "v2.0.1",
"source": {
"type": "git",
"url": "https://github.com/ovh/php-ovh.git",
"reference": "25a97501a150dff8a7848c372b5826395aab4df2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ovh/php-ovh/zipball/25a97501a150dff8a7848c372b5826395aab4df2",
"reference": "25a97501a150dff8a7848c372b5826395aab4df2",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "^6.0"
},
"require-dev": {
"phpdocumentor/phpdocumentor": "2.*",
"phpunit/phpunit": "4.*",
"squizlabs/php_codesniffer": "1.*"
},
"type": "library",
"autoload": {
"psr-4": {
"Ovh\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"description": "Wrapper for OVH APIs",
"time": "2016-02-10T13:16:38+00:00"
},
{
"name": "paragonie/random_compat",
"version": "v9.99.99",
@ -1446,6 +1670,56 @@
],
"time": "2017-02-14T16:28:37+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "psr/log",
"version": "1.1.3",
@ -1613,6 +1887,46 @@
],
"time": "2020-04-07T06:44:48+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/ralouphie/getallheaders.git",
"reference": "120b605dfeb996808c31b6477290a714d356e822"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
"reference": "120b605dfeb996808c31b6477290a714d356e822",
"shasum": ""
},
"require": {
"php": ">=5.6"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpunit": "^5 || ^6.5"
},
"type": "library",
"autoload": {
"files": [
"src/getallheaders.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ralph Khattar",
"email": "ralph.khattar@gmail.com"
}
],
"description": "A polyfill for getallheaders.",
"time": "2019-03-08T08:55:37+00:00"
},
{
"name": "ramsey/uuid",
"version": "3.9.3",

8
flexiapi/config/ovh.php Normal file
View file

@ -0,0 +1,8 @@
<?php
return [
'app_key' => env('OVH_APP_KEY', ''),
'app_secret' => env('OVH_APP_SECRET', ''),
'app_endpoint' => env('OVH_APP_ENDPOINT', 'ovh-eu'),
'app_consumer_key' => env('OVH_APP_CONSUMER_KEY', ''),
];

View file

@ -5,7 +5,7 @@
<div class="collapse navbar-collapse" >
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="{{ route('account.index') }}">FlexiAPI</a>
<a class="nav-link" href="{{ route('account.index') }}">{{ config('app.name') }}</a>
</li>
</ul>
<ul class="navbar-nav">

View file

@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Flexisip API</title>
<title>{{ config('app.name') }}</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>
<body>

View file

@ -5,7 +5,7 @@
<div class="collapse navbar-collapse" >
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="/">FlexiAPI</a>
<a class="nav-link" href="/">{{ config('app.name') }}</a>
</li>
@if (isset($user) && get_class($user) == 'App\Account')
<li class="nav-item active">

View file

@ -0,0 +1,19 @@
<html>
<head>
<title>Authenticate on {{ config('app.name') }}</title>
</head>
<body>
<p>Hello,</p>
<p>
You are trying to authenticate to {{ config('app.name') }} using your email account.<br />
Please follow the unique link bellow to finish the authentication process.
</p>
<p>
<a href="{{ $link }}">{{ $link }}</a>
</p>
<p>
Regards,<br />
The Linphone team.
</p>
</body>
</html>

View file

@ -0,0 +1,9 @@
Hello,
You are trying to authenticate to {{ config('app.name') }} using your email account.
Please follow the unique link bellow to finish the authentication process.
{{ $link }}
Regards,
The Linphone team.

View file

@ -0,0 +1,15 @@
<html>
<head>
<title>Changing your email address</title>
</head>
<body>
<p>Hello,</p>
<p>
You have changed your email address to the current one on {{ config('app.name') }}.
</p>
<p>
Regards,<br />
The Linphone team.
</p>
</body>
</html>

View file

@ -0,0 +1,6 @@
Hello,
You have changed your email address to the current one on {{ config('app.name') }}.
Regards,
The Linphone team.