mirror of
https://gitlab.linphone.org/BC/public/flexisip-account-manager.git
synced 2026-01-17 01:58:07 +00:00
Fix FLEXIAPI-366 Send the voicemails by email
Add a Voicemail UI to listen and delete voicemails in the Admin Account view
This commit is contained in:
parent
76436d7407
commit
eeeb6baf74
28 changed files with 352 additions and 47 deletions
1
cron/flexiapi.cron
Normal file
1
cron/flexiapi.cron
Normal file
|
|
@ -0,0 +1 @@
|
|||
* * * * * apache /opt/belledonne-communications/share/flexisip-account-manager/flexiapi/artisan schedule:run >> /dev/null 2>&1
|
||||
|
|
@ -146,6 +146,11 @@ class Account extends Authenticatable
|
|||
->latest();
|
||||
}
|
||||
|
||||
public function uploadedVoicemails()
|
||||
{
|
||||
return $this->voicemails()->whereNotNull('name');
|
||||
}
|
||||
|
||||
public function vcardsStorage()
|
||||
{
|
||||
return $this->hasMany(VcardStorage::class);
|
||||
|
|
|
|||
|
|
@ -12,19 +12,22 @@ class AccountFile extends Model
|
|||
|
||||
public const VOICEMAIL_CONTENTTYPES = ['audio/opus', 'audio/wav'];
|
||||
public const FILES_PATH = 'files';
|
||||
protected $hidden = ['account_id', 'updated_at'];
|
||||
protected $hidden = ['account_id', 'updated_at', 'sending_by_mail_at', 'sent_by_mail_at', 'sending_by_mail_tryouts'];
|
||||
protected $appends = ['download_url'];
|
||||
protected $casts = [
|
||||
'uploaded_at' => 'datetime',
|
||||
];
|
||||
|
||||
protected static function booted()
|
||||
{
|
||||
static::deleting(function ($category) {
|
||||
Storage::delete($this->getPathAttribute());
|
||||
static::deleting(function (AccountFile $accountFile) {
|
||||
Storage::delete($accountFile->getPathAttribute());
|
||||
});
|
||||
}
|
||||
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo(Account::class);
|
||||
return $this->belongsTo(Account::class)->withoutGlobalScopes();
|
||||
}
|
||||
|
||||
public function getMaxUploadSizeAttribute(): ?int
|
||||
|
|
@ -42,11 +45,30 @@ class AccountFile extends Model
|
|||
return self::FILES_PATH . '/' . $this->attributes['name'];
|
||||
}
|
||||
|
||||
public function getUrlAttribute(): ?string
|
||||
{
|
||||
return !empty($this->attributes['name'])
|
||||
&& !empty($this->attributes['id'])
|
||||
? replaceHost(
|
||||
route('file.show', ['uuid' => $this->attributes['id'], 'name' => $this->attributes['name']]),
|
||||
$this->account->space->host
|
||||
)
|
||||
: null;
|
||||
}
|
||||
|
||||
public function getDownloadUrlAttribute(): ?string
|
||||
{
|
||||
return !empty($this->attributes['name'])
|
||||
&& !empty($this->attributes['id'])
|
||||
? route('file.show', [$this->attributes['id'], $this->attributes['name']])
|
||||
? replaceHost(route(
|
||||
'file.download',
|
||||
['uuid' => $this->attributes['id'], 'name' => $this->attributes['name']]
|
||||
), $this->account->space->host)
|
||||
: null;
|
||||
}
|
||||
|
||||
public function isVoicemailAudio(): bool
|
||||
{
|
||||
return in_array($this->attributes['content_type'], self::VOICEMAIL_CONTENTTYPES);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands\Accounts;
|
||||
|
||||
use App\AccountFile;
|
||||
use App\Mail\Voicemail;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class SendVoicemailsEmails extends Command
|
||||
{
|
||||
protected $signature = 'accounts:send-voicemails-emails {--tryout}';
|
||||
protected $description = 'Send the voicemail emails';
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$voicemails = AccountFile::whereNotNull('uploaded_at')
|
||||
->whereNull('sent_by_mail_at')
|
||||
->where('sending_by_mail_tryouts', '<', is_int($this->option('tryout'))
|
||||
? $this->option('tryout')
|
||||
: 3)
|
||||
->get();
|
||||
|
||||
foreach ($voicemails as $voicemail) {
|
||||
$voicemail->sending_by_mail_at = Carbon::now();
|
||||
$voicemail->save();
|
||||
|
||||
if (Mail::to(users: $voicemail->account)->send(new Voicemail($voicemail))) {
|
||||
$voicemail->sent_by_mail_at = Carbon::now();
|
||||
$this->info('Voicemail sent to ' . $voicemail->account->identifier);
|
||||
} else {
|
||||
$voicemail->sending_by_mail_tryouts++;
|
||||
$this->info('Error sending voicemail to ' . $voicemail->account->identifier);
|
||||
}
|
||||
|
||||
$voicemail->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -162,17 +162,12 @@ function resolveDomain(Request $request): string
|
|||
: $request->space->domain;
|
||||
}
|
||||
|
||||
function maxUploadSize(): ?int
|
||||
function maxUploadSize(): int
|
||||
{
|
||||
$uploadMaxSizeInBytes = ini_parse_quantity(ini_get('upload_max_filesize'));
|
||||
if ($uploadMaxSizeInBytes > 0) {
|
||||
return $uploadMaxSizeInBytes / 1024;
|
||||
}
|
||||
|
||||
$postMaxSizeInBytes = ini_parse_quantity(ini_get('post_max_size'));
|
||||
if ($postMaxSizeInBytes > 0) {
|
||||
return $postMaxSizeInBytes / 1024;
|
||||
}
|
||||
return min(
|
||||
ini_parse_quantity(ini_get('upload_max_filesize')),
|
||||
ini_parse_quantity(ini_get('post_max_size'))
|
||||
);
|
||||
}
|
||||
|
||||
function captchaConfigured(): bool
|
||||
|
|
|
|||
32
flexiapi/app/Http/Controllers/Account/FileController.php
Normal file
32
flexiapi/app/Http/Controllers/Account/FileController.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Account;
|
||||
|
||||
use App\AccountFile;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class FileController extends Controller
|
||||
{
|
||||
public function show(string $uuid, string $name)
|
||||
{
|
||||
$file = AccountFile::findOrFail($uuid);
|
||||
|
||||
if ($file->name != $name) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return Storage::get($file->path);
|
||||
}
|
||||
|
||||
public function download(string $uuid, string $name)
|
||||
{
|
||||
$file = AccountFile::findOrFail($uuid);
|
||||
|
||||
if ($file->name != $name) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return Storage::download($file->path);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Account;
|
||||
|
||||
use App\Account;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class FileController extends Controller
|
||||
{
|
||||
public function delete(int $accountId, string $fileId)
|
||||
{
|
||||
$account = Account::findOrFail($accountId);
|
||||
$file = $account->files()->where('id', $fileId)->firstOrFail();
|
||||
|
||||
return view('admin.account.file.delete', [
|
||||
'account' => $account,
|
||||
'file' => $file
|
||||
]);
|
||||
}
|
||||
|
||||
public function destroy(Request $request, int $accountId, string $fileId)
|
||||
{
|
||||
$account = Account::findOrFail($accountId);
|
||||
$accountFile = $account->files()
|
||||
->where('id', $fileId)
|
||||
->firstOrFail();
|
||||
$accountFile->delete();
|
||||
|
||||
return redirect()->route('admin.account.show', $account)->withFragment('#files');
|
||||
}
|
||||
}
|
||||
|
|
@ -4,24 +4,13 @@ namespace App\Http\Controllers\Api\Account;
|
|||
|
||||
use App\AccountFile;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Rules\AudioMime;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class FileController extends Controller
|
||||
{
|
||||
public function show(string $uuid, string $name)
|
||||
{
|
||||
$file = AccountFile::findOrFail($uuid);
|
||||
|
||||
if ($file->name != $name) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return Storage::download($file->path);
|
||||
}
|
||||
|
||||
public function upload(Request $request, string $uuid)
|
||||
{
|
||||
$file = AccountFile::findOrFail($uuid);
|
||||
|
|
@ -30,14 +19,16 @@ class FileController extends Controller
|
|||
abort(404);
|
||||
}
|
||||
|
||||
$request->validate([
|
||||
'file' => 'required|file|mimetypes:' . $file->content_type
|
||||
]);
|
||||
$request->validate(['file' => 'required|file']);
|
||||
|
||||
if ($file->isVoicemailAudio()) {
|
||||
$request->validate(['file' => [new AudioMime($file)]]);
|
||||
}
|
||||
|
||||
$uploadedFile = $request->file('file');
|
||||
$name = Str::random(8) . '_' . $uploadedFile->getClientOriginalName();
|
||||
|
||||
if ($uploadedFile->storeAs('files', $name)) {
|
||||
if ($uploadedFile->storeAs(AccountFile::FILES_PATH, $name)) {
|
||||
$file->name = $name;
|
||||
$file->size = $uploadedFile->getSize();
|
||||
$file->uploaded_at = Carbon::now();
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ class VoicemailController extends Controller
|
|||
public function store(Request $request, int $accountId)
|
||||
{
|
||||
$account = Account::findOrFail($accountId);
|
||||
|
||||
$request->validate([
|
||||
'sip_from' => 'nullable|starts_with:sip',
|
||||
'content_type' => [
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ 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;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ namespace App\Mail;
|
|||
use App\Account;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ namespace App\Mail;
|
|||
use App\Account;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ namespace App\Mail;
|
|||
use App\Account;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
|
|||
|
|
@ -20,10 +20,8 @@
|
|||
namespace App\Mail;
|
||||
|
||||
use App\Account;
|
||||
use App\ResetPasswordEmailToken;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
|
|||
44
flexiapi/app/Mail/Voicemail.php
Normal file
44
flexiapi/app/Mail/Voicemail.php
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\AccountFile;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Mail\Mailables\Attachment;
|
||||
|
||||
class Voicemail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public function __construct(public AccountFile $accountFile)
|
||||
{
|
||||
}
|
||||
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
return new Envelope(
|
||||
subject: $this->accountFile->account->space->name .
|
||||
': ' .
|
||||
__('New voice message from :sipfrom', ['sipfrom' => $this->accountFile->sip_from]),
|
||||
);
|
||||
}
|
||||
|
||||
public function content(): Content
|
||||
{
|
||||
return new Content(
|
||||
markdown: 'mails.voicemail',
|
||||
);
|
||||
}
|
||||
|
||||
public function attachments(): array
|
||||
{
|
||||
return [
|
||||
Attachment::fromStorage($this->accountFile->path)
|
||||
->withMime($this->accountFile->content_type)
|
||||
];
|
||||
}
|
||||
}
|
||||
38
flexiapi/app/Rules/AudioMime.php
Normal file
38
flexiapi/app/Rules/AudioMime.php
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use App\AccountFile;
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
|
||||
class AudioMime implements Rule
|
||||
{
|
||||
public function __construct(private AccountFile $accountFile)
|
||||
{
|
||||
}
|
||||
|
||||
public function passes($attribute, $file): bool
|
||||
{
|
||||
$mimeType = null;
|
||||
switch ($file->getMimeType()) {
|
||||
case 'audio/opus':
|
||||
$mimeType = 'audio/opus';
|
||||
break;
|
||||
|
||||
case 'audio/vnd.wave':
|
||||
case 'audio/wav':
|
||||
case 'audio/wave':
|
||||
case 'audio/x-wav':
|
||||
case 'audio/x-pn-wav':
|
||||
$mimeType = 'audio/wav';
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->accountFile->content_type == $mimeType;
|
||||
}
|
||||
|
||||
public function message()
|
||||
{
|
||||
return __('The file should have the declared mime-type');
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
namespace App\Rules;
|
||||
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
use Respect\Validation\Validator;
|
||||
use Propaganistas\LaravelPhone\PhoneNumber;
|
||||
|
||||
class IsNotPhoneNumber implements Rule
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ return new class extends Migration
|
|||
$table->string('content_type')->index();
|
||||
$table->text('sip_from')->nullable();
|
||||
$table->dateTime('uploaded_at')->nullable();
|
||||
$table->dateTime('sending_by_mail_at')->nullable();
|
||||
$table->integer('sending_by_mail_tryouts')->default(0);
|
||||
$table->dateTime('sent_by_mail_at')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@
|
|||
"Features": "Fonctionnalités",
|
||||
"Fill the related columns if you want to add an external account as well": "Remplissez également les colonnes suivantes si vous souhaitez ajouter un compte externe",
|
||||
"Fill to change": "Remplir pour changer",
|
||||
"Files": "Fichiers",
|
||||
"From": "Depuis",
|
||||
"Hello":"Bonjour",
|
||||
"Host": "Hôte",
|
||||
|
|
@ -145,6 +146,7 @@
|
|||
"New newsletter subscription": "Nouvelle inscription à votre newsletter",
|
||||
"New Space": "Nouvel Espace",
|
||||
"New user": "Nouvel utilisateur",
|
||||
"New voice message from :sipfrom": "Nouveau message vocal de :sipfrom",
|
||||
"Newsletter registration email address": "Addresse email d'inscription à la liste de diffusion",
|
||||
"Next": "Suivant",
|
||||
"No account yet?": "Pas encore de compte ?",
|
||||
|
|
@ -170,6 +172,7 @@
|
|||
"QR Code scanning": "Scan de QR Code",
|
||||
"Realm": "Royaume",
|
||||
"Recover your account using your email": "Récupérer votre compte avec votre email",
|
||||
"Recorded at": "Enregistré le",
|
||||
"Register": "Inscription",
|
||||
"Registrar": "Registrar",
|
||||
"Registration confirmed": "Confirmation de l'inscription",
|
||||
|
|
@ -246,6 +249,7 @@
|
|||
"Verify": "Vérifier",
|
||||
"Via": "Via",
|
||||
"Visit our user guide" : "Consulter notre guide utilisateur",
|
||||
"Voicemails": "Messages vocaux",
|
||||
"We are pleased to inform you that your account has been successfully created.":"Nous avons le plaisir de vous informer que votre compte a été créé avec succès.",
|
||||
"We inform you that this space will expire on :date, in accordance with the expiration date defined in your subscription.":"Nous vous informons que l'espace expira le :date, conformément à la date d’expiration définie dans votre abonnement.",
|
||||
"We received a request to recover your account on :space": "Nous avons reçu une demande de récupération de votre compte sur :space",
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
The Clean Code ruleset contains rules that enforce a clean code base. This includes rules from SOLID and object calisthenics.
|
||||
</description>
|
||||
|
||||
<rule ref="rulesets/cleancode.xml/ElseExpression" />
|
||||
<rule ref="rulesets/controversial.xml/CamelCaseClassName" />
|
||||
<rule ref="rulesets/controversial.xml/CamelCasePropertyName" />
|
||||
<rule ref="rulesets/controversial.xml/CamelCaseMethodName" />
|
||||
|
|
|
|||
5
flexiapi/public/css/style.css
vendored
5
flexiapi/public/css/style.css
vendored
|
|
@ -190,6 +190,11 @@ body.welcome content {
|
|||
}
|
||||
}
|
||||
|
||||
audio {
|
||||
border-radius: 1rem;
|
||||
max-width: 12rem;
|
||||
}
|
||||
|
||||
hr {
|
||||
border-bottom: 1px solid var(--grey-3);
|
||||
margin: 2rem 0;
|
||||
|
|
|
|||
|
|
@ -177,10 +177,9 @@
|
|||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
|
||||
<div class="card large">
|
||||
<div class="card">
|
||||
<h3>
|
||||
{{ __('Devices') }}
|
||||
</h3>
|
||||
|
|
@ -212,6 +211,53 @@
|
|||
</table>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>
|
||||
{{ __('Voicemails') }}
|
||||
</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ __('Created') }}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if ($account->uploadedVoicemails->isEmpty())
|
||||
<tr class="empty">
|
||||
<td colspan="2">{{ __('Empty') }}</td>
|
||||
</tr>
|
||||
@endif
|
||||
@foreach ($account->uploadedVoicemails as $voicemail)
|
||||
<tr>
|
||||
<td>
|
||||
{{ $voicemail->created_at }}
|
||||
@if ($voicemail->url)
|
||||
<a style="margin-left: 1rem;" href="{{ $voicemail->download_url }}" download>
|
||||
<i class="ph ph-download"></i>
|
||||
</a>
|
||||
@endif
|
||||
@if ($voicemail->sip_from)
|
||||
<br/>
|
||||
<small>{{ $voicemail->sip_from }}</small>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if ($voicemail->url)
|
||||
<audio class="oppose" controls src="{{ $voicemail->url }}"></audio>
|
||||
<a type="button"
|
||||
class="oppose btn tertiary"
|
||||
href="{{ route('admin.account.file.delete', [$account, $voicemail->id]) }}">
|
||||
<i class="ph ph-trash"></i>
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="card large">
|
||||
<a class="btn small oppose" href="{{ route('admin.account.dictionary.create', $account) }}">
|
||||
<i class="ph ph-plus"></i>
|
||||
|
|
|
|||
14
flexiapi/resources/views/mails/voicemail.blade.php
Normal file
14
flexiapi/resources/views/mails/voicemail.blade.php
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
@extends('mails.layout')
|
||||
|
||||
@section('content')
|
||||
# {{ __('New voice message from :sipfrom', ['sipfrom' => $accountFile->sip_from]) }}
|
||||
|
||||
{{ __('New voice message') }}
|
||||
|
||||
{{ __('From') }}: {{ $accountFile->sip_from }}
|
||||
|
||||
{{ __('To') }}: {{ $accountFile->account->identifier }}
|
||||
|
||||
{{ __('Recorded at') }}: {{ $accountFile->created_at->toDateTimeString() }} (UTC)
|
||||
|
||||
@endsection
|
||||
|
|
@ -79,9 +79,10 @@ Route::get('accounts/me/api_key/{auth_token}', [ApiKeyController::class, 'genera
|
|||
Route::get('phone_countries', [PhoneCountryController::class, 'index']);
|
||||
|
||||
Route::group(['middleware' => ['auth.jwt', 'auth.digest_or_key', 'auth.check_blocked']], function () {
|
||||
Route::post('files/{uuid}', [FileController::class, 'upload'])->name('file.upload');
|
||||
|
||||
Route::get('accounts/auth_token/{auth_token}/attach', [AuthTokenController::class, 'attach']);
|
||||
Route::post('account_creation_tokens/consume', [CreationTokenController::class, 'consume']);
|
||||
Route::post('files/{uuid}', 'Api\Account\FileController@upload')->name('file.upload');
|
||||
|
||||
Route::post('push_notification', [PushNotificationController::class, 'push']);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Foundation\Inspiring;
|
||||
use App\Console\Commands\Accounts\ClearFiles;
|
||||
use App\Console\Commands\Accounts\SendVoicemailsEmails;
|
||||
use Illuminate\Support\Facades\Schedule;
|
||||
|
||||
Schedule::command(ClearFiles::class, [7, '--apply'])->daily();
|
||||
Schedule::command(SendVoicemailsEmails::class)->everyMinute();
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ use App\Http\Controllers\Account\ContactVcardController;
|
|||
use App\Http\Controllers\Account\CreationRequestTokenController;
|
||||
use App\Http\Controllers\Account\DeviceController;
|
||||
use App\Http\Controllers\Account\EmailController;
|
||||
use App\Http\Controllers\Account\FileController;
|
||||
use App\Http\Controllers\Account\PasswordController;
|
||||
use App\Http\Controllers\Account\PhoneController;
|
||||
use App\Http\Controllers\Account\ProvisioningController;
|
||||
|
|
@ -39,6 +40,7 @@ use App\Http\Controllers\Admin\Account\CardDavCredentialsController;
|
|||
use App\Http\Controllers\Admin\Account\ContactController;
|
||||
use App\Http\Controllers\Admin\Account\DeviceController as AdminAccountDeviceController;
|
||||
use App\Http\Controllers\Admin\Account\DictionaryController;
|
||||
use App\Http\Controllers\Admin\Account\FileController as AdminFileController;
|
||||
use App\Http\Controllers\Admin\Account\ImportController;
|
||||
use App\Http\Controllers\Admin\Account\StatisticsController as AdminAccountStatisticsController;
|
||||
use App\Http\Controllers\Admin\Account\TypeController;
|
||||
|
|
@ -54,7 +56,6 @@ use App\Http\Controllers\Admin\Space\ContactsListController;
|
|||
use App\Http\Controllers\Admin\Space\EmailServerController;
|
||||
use App\Http\Controllers\Admin\SpaceController;
|
||||
use App\Http\Controllers\Admin\StatisticsController;
|
||||
use App\Http\Controllers\Api\Account\FileController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::redirect('/', 'login')->name('account.home');
|
||||
|
|
@ -77,8 +78,12 @@ Route::middleware(['feature.web_panel_enabled'])->group(function () {
|
|||
});
|
||||
});
|
||||
|
||||
Route::name('file.')->prefix('files')->controller(FileController::class)->group(function () {
|
||||
Route::get('{uuid}/{name}', 'show')->name('show');
|
||||
Route::get('{uuid}/{name}/download', 'download')->name('download');
|
||||
});
|
||||
|
||||
Route::group(['middleware' => ['auth.jwt', 'auth.digest_or_key']], function () {
|
||||
Route::get('files/{uuid}/{name}', [FileController::class, 'show'])->name('file.show');
|
||||
|
||||
Route::get('provisioning/me', [ProvisioningController::class, 'me'])->name('provisioning.me');
|
||||
|
||||
|
|
@ -341,6 +346,11 @@ Route::middleware(['feature.web_panel_enabled'])->group(function () {
|
|||
Route::get('call_logs', 'showCallLogs')->name('show_call_logs');
|
||||
Route::post('/', 'edit')->name('edit');
|
||||
});
|
||||
|
||||
Route::name('file.')->prefix('{account}/files')->controller(AdminFileController::class)->group(function () {
|
||||
Route::get('{file_id}/delete', 'delete')->name('delete');
|
||||
Route::delete('{file_id}', 'destroy')->name('destroy');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ class ApiVoicemailTest extends TestCase
|
|||
'file' => UploadedFile::fake()->create('audio.opus', 500, 'audio/opus')
|
||||
])->assertNotFound();
|
||||
|
||||
$this->head($file->json()['download_url'])->assertOk();
|
||||
$this->head($file->json()['download_url'])->dump()->assertOk();
|
||||
|
||||
// Delete the file
|
||||
$this->keyAuthenticated($account)
|
||||
|
|
@ -153,5 +153,23 @@ class ApiVoicemailTest extends TestCase
|
|||
->assertOk();
|
||||
|
||||
$this->head($file->json()['download_url'])->assertNotFound();
|
||||
|
||||
/* To try out with a real file
|
||||
$accountFile = $this->keyAuthenticated($account)
|
||||
->json('POST', $this->route, [
|
||||
'content_type' => 'audio/wav'
|
||||
])->assertCreated();
|
||||
|
||||
$uuid = $accountFile->json()['id'];
|
||||
|
||||
$this->keyAuthenticated($account)
|
||||
->json('POST', $this->uploadRoute . $uuid, data: [
|
||||
'file' => new UploadedFile(
|
||||
storage_path("audio.wav"),
|
||||
'audio.wav',
|
||||
test: true,
|
||||
)
|
||||
])->assertOk();
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ cp flexiapi/composer.json "$RPM_BUILD_ROOT%{opt_dir}/flexiapi"
|
|||
cp README* "$RPM_BUILD_ROOT%{opt_dir}/"
|
||||
cp INSTALL* "$RPM_BUILD_ROOT%{opt_dir}/"
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/cron.daily
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/cron.d
|
||||
|
||||
mkdir -p $RPM_BUILD_ROOT%{apache_conf_path}
|
||||
cp httpd/flexisip-account-manager.conf "$RPM_BUILD_ROOT%{apache_conf_path}/"
|
||||
|
|
@ -66,6 +67,13 @@ cp httpd/flexisip-account-manager.conf "$RPM_BUILD_ROOT%{apache_conf_path}/"
|
|||
chmod +x "$RPM_BUILD_ROOT/etc/cron.daily/flexiapi.redhat"
|
||||
%endif
|
||||
|
||||
cp cron/flexiapi.cron "$RPM_BUILD_ROOT/etc/cron.d/flexiapi"
|
||||
chmod +x "$RPM_BUILD_ROOT/etc/cron.d/flexiapi"
|
||||
|
||||
%if %{with deb}
|
||||
sed 's/apache/www-data/g' "$RPM_BUILD_ROOT/etc/cron.d/flexiapi"
|
||||
%endif
|
||||
|
||||
# POST INSTALLATION
|
||||
|
||||
%posttrans
|
||||
|
|
@ -161,6 +169,7 @@ fi
|
|||
|
||||
%exclude %{opt_dir}/flexiapi/storage/
|
||||
|
||||
%config /etc/cron.d/flexiapi
|
||||
%config(noreplace) %{apache_conf_path}/flexisip-account-manager.conf
|
||||
%if %{with deb}
|
||||
%config(noreplace) /etc/cron.daily/flexiapi.debian
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue