mirror of
https://gitlab.linphone.org/BC/public/flexisip-account-manager.git
synced 2026-01-17 10:08:05 +00:00
Fix FLEXIAPI-224 Add a console script to send Space Expiration emails
This commit is contained in:
parent
48961ea194
commit
b0b6ab2c51
13 changed files with 129 additions and 14 deletions
|
|
@ -35,6 +35,7 @@ v1.7
|
||||||
- Fix FLEXIAPI-287 Refactor the emails templates
|
- Fix FLEXIAPI-287 Refactor the emails templates
|
||||||
- Fix FLEXIAPI-286 Send an account_recovery_token using a push notification and protect the account recovery using phone page with the account_recovery_token
|
- Fix FLEXIAPI-286 Send an account_recovery_token using a push notification and protect the account recovery using phone page with the account_recovery_token
|
||||||
- Fix FLEXIAPI-293 Remove the (long) outdated general documentation
|
- Fix FLEXIAPI-293 Remove the (long) outdated general documentation
|
||||||
|
- Fix FLEXIAPI-224 Add a console script to send Space Expiration emails
|
||||||
|
|
||||||
v1.6
|
v1.6
|
||||||
----
|
----
|
||||||
|
|
|
||||||
|
|
@ -61,9 +61,9 @@ php artisan spaces:create-update beta.sip beta.myhost.com "Beta Space"
|
||||||
|
|
||||||
5. Configure your Spaces.
|
5. Configure your Spaces.
|
||||||
|
|
||||||
6. Remove the instance based environnement variables (see **Changed** above) and configure them directly in the spaces using the API or Web Panel.
|
6. (Optional) Import the old instance DotEnv environnement variables into a space.
|
||||||
|
|
||||||
7. (Optional) Import the old instance DotEnv environnement variables into a space.
|
7. Remove the instance based environnement variables (see **Changed** above) and configure them directly in the spaces using the API or Web Panel.
|
||||||
|
|
||||||
⚠️ Be careful, during this import only the project DotEnv file variables will be imported, other environnement (eg. set in Apache, nginx or Docker) will be ignored.
|
⚠️ Be careful, during this import only the project DotEnv file variables will be imported, other environnement (eg. set in Apache, nginx or Docker) will be ignored.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,5 @@ cd /opt/belledonne-communications/share/flexisip-account-manager/flexiapi/
|
||||||
sudo -su www-data && php artisan digest:clear-nonces 60
|
sudo -su www-data && php artisan digest:clear-nonces 60
|
||||||
sudo -su www-data && php artisan accounts:clear-api-keys 60
|
sudo -su www-data && php artisan accounts:clear-api-keys 60
|
||||||
sudo -su www-data && php artisan accounts:clear-accounts-tombstones 7 --apply
|
sudo -su www-data && php artisan accounts:clear-accounts-tombstones 7 --apply
|
||||||
sudo -su www-data && php artisan accounts:clear-unconfirmed 30 --apply
|
sudo -su www-data && php artisan accounts:clear-unconfirmed 30 --apply
|
||||||
|
sudo -su www-data && php artisan spaces:expiration-emails
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,5 @@ cd /opt/belledonne-communications/share/flexisip-account-manager/flexiapi/
|
||||||
php artisan digest:clear-nonces 60
|
php artisan digest:clear-nonces 60
|
||||||
php artisan accounts:clear-api-keys 60
|
php artisan accounts:clear-api-keys 60
|
||||||
php artisan accounts:clear-accounts-tombstones 7 --apply
|
php artisan accounts:clear-accounts-tombstones 7 --apply
|
||||||
php artisan accounts:clear-unconfirmed 30 --apply
|
php artisan accounts:clear-unconfirmed 30 --apply
|
||||||
|
php artisan spaces:expiration-emails
|
||||||
|
|
@ -80,7 +80,6 @@ class CreateAdminAccount extends Command
|
||||||
$account = new Account;
|
$account = new Account;
|
||||||
$account->username = $username;
|
$account->username = $username;
|
||||||
$account->domain = $domain;
|
$account->domain = $domain;
|
||||||
$account->email = 'admin_test@sip.example.org';
|
|
||||||
$account->activated = true;
|
$account->activated = true;
|
||||||
$account->user_agent = 'Test';
|
$account->user_agent = 'Test';
|
||||||
$account->ip_address = '0.0.0.0';
|
$account->ip_address = '0.0.0.0';
|
||||||
|
|
|
||||||
57
flexiapi/app/Console/Commands/Spaces/ExpirationEmails.php
Normal file
57
flexiapi/app/Console/Commands/Spaces/ExpirationEmails.php
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands\Spaces;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
use App\Mail\ExpiringSpace;
|
||||||
|
use App\Space;
|
||||||
|
|
||||||
|
class ExpirationEmails extends Command
|
||||||
|
{
|
||||||
|
protected $signature = 'spaces:expiration-emails {days?}';
|
||||||
|
protected $description = 'Send an expiration email on the designated configured days before expiration. Days must be ordered descending and comma separated (eg. 7,3,1)';
|
||||||
|
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$days = ['7','3','1'];
|
||||||
|
|
||||||
|
if ($this->argument('days')) {
|
||||||
|
preg_match_all('/\d++/', $this->argument('days'), $matches);
|
||||||
|
|
||||||
|
if (!empty($matches[0])) {
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
while ($i + 1 < count($matches[0]) && (int)$matches[0][$i] > (int)$matches[0][$i + 1]) {
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($i != count($matches[0]) - 1) {
|
||||||
|
$this->error('The days must be integer, ordered descending and comma separated');
|
||||||
|
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$days = $matches[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$expiringSpaces = Space::whereNotNull('expire_at')->whereDate('expire_at', '>=', Carbon::now())->get();
|
||||||
|
|
||||||
|
foreach ($expiringSpaces as $expiringSpace) {
|
||||||
|
if (in_array($expiringSpace->daysLeft, $days)) {
|
||||||
|
$this->info($expiringSpace->name . ' (' . $expiringSpace->host . ') is expiring in ' . $expiringSpace->daysLeft . ' days');
|
||||||
|
|
||||||
|
$admins = $expiringSpace->admins()->withoutGlobalScopes()->whereNotNull('email')->get();
|
||||||
|
|
||||||
|
$this->info('Sending an email to the admins ' . $admins->implode('email', ','));
|
||||||
|
|
||||||
|
foreach ($admins as $admin) {
|
||||||
|
Mail::to($admin->email)->send(new ExpiringSpace($expiringSpace));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
flexiapi/app/Mail/ExpiringSpace.php
Normal file
36
flexiapi/app/Mail/ExpiringSpace.php
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Mail;
|
||||||
|
|
||||||
|
use App\Space;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Mail\Mailables\Content;
|
||||||
|
use Illuminate\Mail\Mailables\Envelope;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class ExpiringSpace extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
public Space $space
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function envelope(): Envelope
|
||||||
|
{
|
||||||
|
return new Envelope(
|
||||||
|
subject: $this->space->name . ': '. __('Space is expiring in :days days', ['days' => $this->space->daysLeft]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function content(): Content
|
||||||
|
{
|
||||||
|
return new Content(
|
||||||
|
markdown: 'mails.expiring_space',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -66,7 +66,7 @@ class Space extends Model
|
||||||
];
|
];
|
||||||
|
|
||||||
public const HOST_REGEX = '[\w\-]+';
|
public const HOST_REGEX = '[\w\-]+';
|
||||||
public const DOMAIN_REGEX = '(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63}$)';
|
public const DOMAIN_REGEX = '(?=^.{4,253}$)(^((?!-)[a-z0-9-]{1,63}(?<!-)\.)+[a-z]{2,63}$)';
|
||||||
|
|
||||||
public function accounts()
|
public function accounts()
|
||||||
{
|
{
|
||||||
|
|
@ -129,7 +129,7 @@ class Space extends Model
|
||||||
public function getDaysLeftAttribute(): ?int
|
public function getDaysLeftAttribute(): ?int
|
||||||
{
|
{
|
||||||
if ($this->expire_at != null) {
|
if ($this->expire_at != null) {
|
||||||
return (int)$this->expire_at->diffInDays(Carbon::now());
|
return (int)$this->expire_at->diffInDays(Carbon::now()) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -167,6 +167,7 @@
|
||||||
"Sip Adress": "Adresse SIP",
|
"Sip Adress": "Adresse SIP",
|
||||||
"SIP Domain": "Domaine SIP",
|
"SIP Domain": "Domaine SIP",
|
||||||
"Space": "Espace",
|
"Space": "Espace",
|
||||||
|
"Space is expiring in :days days": "Votre Espace expire dans %d jours",
|
||||||
"Spaces": "Espaces",
|
"Spaces": "Espaces",
|
||||||
"Statistics": "Statistiques",
|
"Statistics": "Statistiques",
|
||||||
"Subdomain": "Sous-domaine",
|
"Subdomain": "Sous-domaine",
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if ($account->accountRecoveryTokens)
|
@if ($account->accountRecoveryTokens->isNotEmpty())
|
||||||
<div class="card large">
|
<div class="card large">
|
||||||
<h3>Account Recovery Tokens</h3>
|
<h3>Account Recovery Tokens</h3>
|
||||||
<table>
|
<table>
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,11 @@
|
||||||
@else
|
@else
|
||||||
<i class="ph">infinity</i>
|
<i class="ph">infinity</i>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@if ($space->expire_at)
|
||||||
|
<br />
|
||||||
|
<small>{{ $space->expire_at->format('d-m-Y') }}</small>
|
||||||
|
@endif
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
|
||||||
14
flexiapi/resources/views/mails/expiring_space.blade.php
Normal file
14
flexiapi/resources/views/mails/expiring_space.blade.php
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
@extends('mails.layout')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
# {{ $space->name }} is expiring in {{ $space->daysLeft }} days
|
||||||
|
|
||||||
|
You are one of the administrator of the {{ $space->name }} space configured on our service.
|
||||||
|
|
||||||
|
We inform you that this Space is officialy expiring on **{{ $space->expire_at->format('d-m-Y') }}**.
|
||||||
|
|
||||||
|
After that day you and your registered users will not be able to use the features provided by your subscription anymore.
|
||||||
|
|
||||||
|
Be sure to renew your subscription if you would like to continue to use our services.
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
@ -203,6 +203,12 @@ Route::middleware(['web_panel_enabled', 'space.check'])->group(function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::name('account.')->prefix('accounts')->group(function () {
|
Route::name('account.')->prefix('accounts')->group(function () {
|
||||||
|
Route::name('import.')->prefix('import')->controller(AccountImportController::class)->group(function () {
|
||||||
|
Route::get('/', 'create')->name('create');
|
||||||
|
Route::post('/', 'store')->name('store');
|
||||||
|
Route::post('handle', 'handle')->name('handle');
|
||||||
|
});
|
||||||
|
|
||||||
Route::middleware(['intercom_features'])->group(function () {
|
Route::middleware(['intercom_features'])->group(function () {
|
||||||
Route::name('type.')->prefix('types')->controller(AccountTypeController::class)->group(function () {
|
Route::name('type.')->prefix('types')->controller(AccountTypeController::class)->group(function () {
|
||||||
Route::get('/', 'index')->name('index');
|
Route::get('/', 'index')->name('index');
|
||||||
|
|
@ -260,12 +266,6 @@ Route::middleware(['web_panel_enabled', 'space.check'])->group(function () {
|
||||||
Route::get('send', 'send')->name('send');
|
Route::get('send', 'send')->name('send');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::name('import.')->prefix('import')->controller(AccountImportController::class)->group(function () {
|
|
||||||
Route::get('/', 'create')->name('create');
|
|
||||||
Route::post('/', 'store')->name('store');
|
|
||||||
Route::post('handle', 'handle')->name('handle');
|
|
||||||
});
|
|
||||||
|
|
||||||
Route::name('contact.')->prefix('{account}/contacts')->controller(AccountContactController::class)->group(function () {
|
Route::name('contact.')->prefix('{account}/contacts')->controller(AccountContactController::class)->group(function () {
|
||||||
Route::get('/', 'index')->name('index');
|
Route::get('/', 'index')->name('index');
|
||||||
Route::get('create', 'create')->name('create');
|
Route::get('create', 'create')->name('create');
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue