Complete the documentation regarding how DotEnv configuration is handled

Add a confirmation flow using a email when an account tries to change one
This commit is contained in:
Timothée Jaussoin 2020-09-14 16:41:47 +02:00
parent 30fcf9792f
commit 8fd85c00d2
12 changed files with 161 additions and 10 deletions

View file

@ -111,6 +111,8 @@ php artisan migrate:rollback
php artisan migrate
```
This API is having it's own README file in the `flexiapi` directory.
### 5. Packaging
--------------------
To build a rpm package on centos7:

1
flexiapi/.gitignore vendored
View file

@ -2,6 +2,7 @@
/public/hot
/public/storage
/storage/*.key
/storage/*.sqlite
/vendor
.env
.env.backup

View file

@ -2,6 +2,14 @@
This tool connects to the Flexisip CLI interface and exposes several endpoints to request and manage it.
## DotEnv configuration
FlexiAPI relies on [DotEnv](https://github.com/vlucas/phpdotenv) to be configured. This configuration can be accessed using the existing `.env` file that can be itself overwritten by an environnement variables.
Thoses variables can then be set using Docker-Compose, a bash script or a web-server for example.
If you're installing FlexiAPI from the RPM package you can find the configuration file at `/etc/flexisip-account-manager/flexiapi.env`.
## Setup
Clone the repository, install the dependencies and generate a key.

View file

@ -25,7 +25,7 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
class Account extends Authenticatable
{
protected $connection = 'external';
protected $with = ['passwords', 'admin'];
protected $with = ['passwords', 'admin', 'emailChanged'];
protected $dates = ['creation_time'];
public $timestamps = false;
@ -56,6 +56,11 @@ class Account extends Authenticatable
return $this->hasOne('App\Admin');
}
public function emailChanged()
{
return $this->hasOne('App\EmailChanged');
}
public function getIdentifierAttribute()
{
return $this->attributes['username'].'@'.$this->attributes['domain'];

View file

@ -0,0 +1,16 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class EmailChanged extends Model
{
protected $connection = 'local';
protected $table = 'email_changed';
public function account()
{
return $this->belongsTo('App\Account');
}
}

View file

@ -2,11 +2,14 @@
namespace App\Http\Controllers\Account;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use App\Http\Controllers\Controller;
use App\Mail\ChangingEmail;
use App\Mail\ChangedEmail;
use App\EmailChanged;
class EmailController extends Controller
{
@ -17,18 +20,46 @@ class EmailController extends Controller
]);
}
public function update(Request $request)
public function requestUpdate(Request $request)
{
$request->validate([
'email' => 'required|unique:external.accounts,email|different:email_current|confirmed|email',
'email' => 'required|different:email_current|confirmed|email',
]);
$account = $request->user();
$account->email = $request->get('email');
$account->save();
// Remove all the old requests
EmailChanged::where('account_id', $request->user()->id)->delete();
Mail::to($account)->send(new ChangedEmail());
// Create a new one
$emailChanged = new EmailChanged;
$emailChanged->new_email = $request->get('email');
$emailChanged->hash = Str::random(16);
$emailChanged->account_id = $request->user()->id;
$emailChanged->save();
$request->user()->refresh();
Mail::to($request->user())->send(new ChangingEmail($request->user()));
$request->session()->flash('success', 'An email was sent with a confirmation link. Please click it to update your email address.');
return redirect()->route('account.panel');
}
public function update(Request $request, string $hash)
{
$account = $request->user();
if ($account->emailChanged && $account->emailChanged->hash == $hash) {
$account->email = $account->emailChanged->new_email;
$account->save();
Mail::to($account)->send(new ChangedEmail());
$account->emailChanged->delete();
$request->session()->flash('success', 'Email successfully updated');
return redirect()->route('account.panel');
}
abort(404);
}
}

View file

@ -0,0 +1,29 @@
<?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 ChangingEmail extends Mailable
{
use Queueable, SerializesModels;
private $_account;
public function __construct(Account $account)
{
$this->_account = $account;
}
public function build()
{
return $this->view('mails.changing_email')
->text('mails.changing_email_text')
->with(['account' => $this->_account]);
}
}

View file

@ -0,0 +1,24 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddEmailChangedTable extends Migration
{
public function up()
{
Schema::connection('local')->create('email_changed', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('account_id')->unsigned()->unique();
$table->string('new_email');
$table->string('hash');
$table->timestamps();
});
}
public function down()
{
Schema::connection('local')->dropIfExists('email_changed');
}
}

View file

@ -10,7 +10,7 @@
<p>No email yet</p>
@endif
{!! Form::open(['route' => 'account.email.update']) !!}
{!! Form::open(['route' => 'account.email.request_update']) !!}
<div class="form-group">
{!! Form::label('email', 'New email') !!}
{!! Form::email('email', old('email'), ['class' => 'form-control', 'placeholder' => 'bob@example.net', 'required']) !!}

View file

@ -0,0 +1,24 @@
<html>
<head>
<title>Changing your email address</title>
</head>
<body>
<p>Hello,</p>
<p>
You requested to change your email address from {{ $account->email }} to {{ $account->emailChanged->email }} on {{ config('app.name') }}.
</p>
<p>
To confirm this change please click on the following link:
<a href="{{ route('account.email.update', ['hash' => $account->emailChanged->hash]) }}">
{{ route('account.email.update', ['hash' => $account->emailChanged->hash]) }}
</a>.
</p>
<p>
If you are not at the origin of this change just ignore this message.
</p>
<p>
Regards,<br />
{{ config('mail.signature') }}
</p>
</body>
</html>

View file

@ -0,0 +1,10 @@
Hello,
You requested to change your email address from {{ $account->email }} to {{ $account->emailChanged->email }} on {{ config('app.name') }}.
To confirm this change please click on the following link: {{ route('account.email.request_update', $account->emailChanged->hash) }}.
If you are not at the origin of this change just ignore this message.
Regards,
{{ config('mail.signature') }}

View file

@ -51,7 +51,8 @@ Route::group(['middleware' => 'auth'], function () {
Route::delete('delete', 'AccountController@destroy')->name('account.destroy');
Route::get('email', 'Account\EmailController@show')->name('account.email');
Route::post('email', 'Account\EmailController@update')->name('account.email.update');
Route::post('email/request', 'Account\EmailController@requestUpdate')->name('account.email.request_update');
Route::get('email/{hash}', 'Account\EmailController@update')->name('account.email.update');
Route::get('password', 'Account\PasswordController@show')->name('account.password');
Route::post('password', 'Account\PasswordController@update')->name('account.password.update');