mirror of
https://gitlab.linphone.org/BC/public/flexisip-account-manager.git
synced 2026-04-17 19:58:27 +00:00
Fix FLEXIAPI-272 Add Space based email server integration
This commit is contained in:
parent
fd0fcd7045
commit
672d6291b7
28 changed files with 652 additions and 29 deletions
|
|
@ -28,6 +28,7 @@ v1.7
|
|||
- Fix FLEXIAPI-278 Complete and reorganize the Markdown documentation
|
||||
- Fix FLEXIAPI-233 Add External Accounts (new version)
|
||||
- Fix FLEXIAPI-277 Restrict authorized ini keys that can be set to prevent conflict with the existing ones set in the UI
|
||||
- Fix FLEXIAPI-272 Add Space based email server integration
|
||||
|
||||
v1.6
|
||||
----
|
||||
|
|
|
|||
|
|
@ -1,5 +1,21 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2020 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;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin\Space;
|
||||
|
||||
use App\Space;
|
||||
use App\SpaceEmailServer;
|
||||
|
||||
use App\Http\Requests\EmailServer\CreateUpdate;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class EmailServerController extends Controller
|
||||
{
|
||||
public function show(int $spaceId)
|
||||
{
|
||||
$space = Space::findOrFail($spaceId);
|
||||
|
||||
return view('admin.space.email_server.show', [
|
||||
'space' => $space,
|
||||
'emailServer' => $space->emailServer ?? new SpaceEmailServer
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(CreateUpdate $request, int $spaceId)
|
||||
{
|
||||
$space = Space::findOrFail($spaceId);
|
||||
$emailServer = $space->emailServer ?? new SpaceEmailServer;
|
||||
|
||||
$emailServer->space_id = $space->id;
|
||||
$emailServer->host = $request->get('host');
|
||||
$emailServer->port = $request->get('port');
|
||||
$emailServer->username = $request->get('username');
|
||||
$emailServer->password = $request->get('password');
|
||||
$emailServer->from_address = $request->get('from_address') ?? null;
|
||||
$emailServer->from_name = $request->get('from_name') ?? null;
|
||||
$emailServer->signature = $request->get('signature') ?? null;
|
||||
|
||||
$emailServer->save();
|
||||
|
||||
return redirect()->route('admin.spaces.integration', $spaceId);
|
||||
}
|
||||
|
||||
public function delete(int $spaceId)
|
||||
{
|
||||
$space = Space::findOrFail($spaceId);
|
||||
|
||||
return view('admin.space.email_server.delete', [
|
||||
'space' => $space
|
||||
]);
|
||||
}
|
||||
|
||||
public function destroy(int $spaceId)
|
||||
{
|
||||
$space = Space::findOrFail($spaceId);
|
||||
$space->emailServer->delete();
|
||||
|
||||
return redirect()->route('admin.spaces.integration', $spaceId);
|
||||
}
|
||||
}
|
||||
|
|
@ -104,6 +104,13 @@ class SpaceController extends Controller
|
|||
]);
|
||||
}
|
||||
|
||||
public function integration(Space $space)
|
||||
{
|
||||
return view('admin.space.integration', [
|
||||
'space' => $space
|
||||
]);
|
||||
}
|
||||
|
||||
public function configurationUpdate(Request $request, Space $space)
|
||||
{
|
||||
$space = $this->setConfiguration($request, $space);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\EmailServer\CreateUpdate;
|
||||
use App\Space;
|
||||
use App\SpaceEmailServer;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class EmailServerController extends Controller
|
||||
{
|
||||
public function show(string $host)
|
||||
{
|
||||
return Space::where('host', $host)->firstOrFail()->emailServer()->firstOrFail();
|
||||
}
|
||||
|
||||
public function store(CreateUpdate $request, string $host)
|
||||
{
|
||||
$space = Space::where('host', $host)->firstOrFail();
|
||||
$emailServer = $space->emailServer ?? new SpaceEmailServer;
|
||||
|
||||
$emailServer->space_id = $space->id;
|
||||
$emailServer->host = $request->get('host');
|
||||
$emailServer->port = $request->get('port');
|
||||
$emailServer->username = $request->get('username');
|
||||
$emailServer->password = $request->get('password');
|
||||
$emailServer->from_address = $request->get('from_address') ?? null;
|
||||
$emailServer->from_name = $request->get('from_name') ?? null;
|
||||
$emailServer->signature = $request->get('signature') ?? null;
|
||||
|
||||
$emailServer->save();
|
||||
|
||||
return $emailServer;
|
||||
}
|
||||
|
||||
public function destroy(string $host)
|
||||
{
|
||||
$space = Space::where('host', $host)->firstOrFail();
|
||||
return $space->emailServer->delete();
|
||||
}
|
||||
}
|
||||
|
|
@ -90,7 +90,7 @@ class Kernel extends HttpKernel
|
|||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
||||
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
|
||||
'space.expired' => \App\Http\Middleware\IsSpaceExpired::class,
|
||||
'space.check' => \App\Http\Middleware\SpaceCheck::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
'localization' => \App\Http\Middleware\Localization::class,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use Illuminate\Http\Request;
|
|||
use Illuminate\Support\Facades\Config;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class IsSpaceExpired
|
||||
class SpaceCheck
|
||||
{
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
|
|
@ -29,6 +29,25 @@ class IsSpaceExpired
|
|||
abort(403, 'The related Space has expired');
|
||||
}
|
||||
|
||||
// Custom email integration
|
||||
if ($space->emailServer) {
|
||||
$config = [
|
||||
'driver' => config('mail.driver'),
|
||||
'encryption' => config('mail.encryption'),
|
||||
'host' => $space->emailServer->host,
|
||||
'port' => $space->emailServer->port,
|
||||
'from' => [
|
||||
'address' => $space->emailServer->from_address,
|
||||
'name' => $space->emailServer->from_name
|
||||
],
|
||||
'username' => $space->emailServer->username,
|
||||
'password' => $space->emailServer->password,
|
||||
'signature' => $space->emailServer->signature ?? config('mail.signature')
|
||||
];
|
||||
|
||||
Config::set('mail', $config);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
38
flexiapi/app/Http/Requests/EmailServer/CreateUpdate.php
Normal file
38
flexiapi/app/Http/Requests/EmailServer/CreateUpdate.php
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2023 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\Http\Requests\EmailServer;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
use App\EmailServer;
|
||||
use App\Rules\Domain;
|
||||
|
||||
class CreateUpdate extends FormRequest
|
||||
{
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'host' => ['required', new Domain()],
|
||||
'port' => 'required|integer',
|
||||
'from_address' => 'nullable|email',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,21 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2020 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;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,21 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2020 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;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,21 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2020 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;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
|
@ -11,6 +27,8 @@ class Space extends Model
|
|||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $with = ['emailServer'];
|
||||
|
||||
public const FORBIDDEN_KEYS = [
|
||||
'disable_chat_feature',
|
||||
'disable_meetings_feature',
|
||||
|
|
@ -60,6 +78,11 @@ class Space extends Model
|
|||
return $this->accounts()->where('admin', true);
|
||||
}
|
||||
|
||||
public function emailServer()
|
||||
{
|
||||
return $this->hasOne(SpaceEmailServer::class);
|
||||
}
|
||||
|
||||
public function scopeNotFull(Builder $query)
|
||||
{
|
||||
return $query->where('max_accounts', 0)
|
||||
|
|
|
|||
34
flexiapi/app/SpaceEmailServer.php
Normal file
34
flexiapi/app/SpaceEmailServer.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2020 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;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class SpaceEmailServer extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $hidden = ['space_id'];
|
||||
|
||||
public function space()
|
||||
{
|
||||
return $this->belongsTo(Space::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('space_email_servers', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
$table->string('host', 64);
|
||||
$table->integer('port');
|
||||
$table->string('username', 128)->nullable();
|
||||
$table->string('password', 128)->nullable();
|
||||
$table->string('from_address', 128)->nullable();
|
||||
$table->string('from_name', 128)->nullable();
|
||||
$table->string('signature', 256)->nullable();
|
||||
|
||||
$table->bigInteger('space_id')->unsigned();
|
||||
$table->foreign('space_id')->references('id')
|
||||
->on('spaces')->onDelete('cascade');
|
||||
|
||||
$table->unique('space_id');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('space_email_servers');
|
||||
}
|
||||
};
|
||||
|
|
@ -63,6 +63,7 @@
|
|||
"Edit": "Éditer",
|
||||
"Email registration": "Inscription par email",
|
||||
"Email": "Email",
|
||||
"Email Server": "Serveur Mail",
|
||||
"Empty": "Vide",
|
||||
"Enable the web interface": "Activer l'interface web",
|
||||
"Enabled": "Activé",
|
||||
|
|
@ -89,6 +90,7 @@
|
|||
"In ini format, will complete the other settings": "Au format ini, complètera les autres paramètres",
|
||||
"In lowercase letters": "En minuscules",
|
||||
"Information": "Informations",
|
||||
"Integration": "Intégration",
|
||||
"Intercom features": "Fonctionnalités d'interphonie",
|
||||
"It might actually disable this page, be careful": "Cette page pourrait être désactivée, faites attention",
|
||||
"Key": "Clef",
|
||||
|
|
|
|||
4
flexiapi/public/css/form.css
vendored
4
flexiapi/public/css/form.css
vendored
|
|
@ -35,6 +35,10 @@ p .btn {
|
|||
text-align: right;
|
||||
}
|
||||
|
||||
p .btn.oppose {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.btn[disabled] {
|
||||
color: var(--main-5);
|
||||
border-color: var(--main-5);
|
||||
|
|
|
|||
36
flexiapi/public/css/style.css
vendored
36
flexiapi/public/css/style.css
vendored
|
|
@ -342,6 +342,23 @@ content section {
|
|||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
content:has(section.documentation) {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
content section.documentation {
|
||||
max-width: calc(100% - 35rem);
|
||||
margin: 0;
|
||||
margin-left: 35rem;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
content section.documentation {
|
||||
max-width: 100%;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
form section {
|
||||
margin: initial;
|
||||
max-width: initial;
|
||||
|
|
@ -787,14 +804,29 @@ select.list_toggle {
|
|||
/** Specific elements */
|
||||
|
||||
.table-of-contents {
|
||||
max-width: 40%;
|
||||
float: right;
|
||||
max-width: 33rem;
|
||||
max-height: calc(100vh - 19rem);
|
||||
overflow-y: scroll;
|
||||
position: fixed;
|
||||
top: 11rem;
|
||||
left: 0;
|
||||
padding: 2rem;
|
||||
box-sizing: border-box;
|
||||
background-color: var(--grey-1);
|
||||
border-radius: 0 1rem 1rem 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
.table-of-contents {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: var(--grey-1);
|
||||
border-radius: 1rem;
|
||||
padding: 1.5rem;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 1rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
@extends('layouts.main', ['welcome' => true])
|
||||
|
||||
@section('content')
|
||||
<div>
|
||||
{{-- This view is only a wrapper for the markdown page --}}
|
||||
{!! $documentation !!}
|
||||
</div>
|
||||
<section class="documentation">
|
||||
{{-- This view is only a wrapper for the markdown page --}}
|
||||
{!! $documentation !!}
|
||||
</section>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
@extends('layouts.main')
|
||||
|
||||
@section('breadcrumb')
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{{ route('admin.spaces.index') }}">{{ __('Spaces') }}</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{{ route('admin.spaces.show', $space) }}">
|
||||
{{ $space->name }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{{ route('admin.spaces.integration', $space) }}">{{ __('Integration') }}</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ __('Email Server') }} - {{ __('Delete' )}}</li>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<header>
|
||||
<h1><i class="ph">trash</i> {{ __('Delete') }}</h1>
|
||||
|
||||
<a href="{{ route('admin.spaces.integration', ['space' => $space]) }}" class="btn btn-secondary oppose">{{ __('Cancel') }}</a>
|
||||
<input form="delete" class="btn" type="submit" value="{{ __('Delete') }}">
|
||||
</header>
|
||||
<form id="delete" method="POST" action="{{ route('admin.spaces.email.destroy', $space->id) }}" accept-charset="UTF-8">
|
||||
@csrf
|
||||
@method('delete')
|
||||
|
||||
<div class="large">
|
||||
<p>{{ __('You are going to permanently delete the following element. Please confirm your action.') }}<br />
|
||||
<b><i class="ph">envelope</i> {{ $space->emailServer->host }}</b>
|
||||
</p>
|
||||
<input name="account_id" type="hidden" value="{{ $space->id }}">
|
||||
</div>
|
||||
<div>
|
||||
</div>
|
||||
</form>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
@extends('layouts.main')
|
||||
|
||||
@section('breadcrumb')
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{{ route('admin.spaces.index') }}">{{ __('Spaces') }}</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{{ route('admin.spaces.show', $space) }}">
|
||||
{{ $space->name }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{{ route('admin.spaces.integration', $space) }}">{{ __('Integration') }}</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ __('Email Server') }}</li>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<header>
|
||||
<h1><i class="ph">envelope</i> {{ $space->name }}</h1>
|
||||
</header>
|
||||
|
||||
|
||||
<form method="POST"
|
||||
action="{{ route('admin.spaces.email.store', $space->id) }}"
|
||||
id="show" accept-charset="UTF-8">
|
||||
@csrf
|
||||
@method('post')
|
||||
<div>
|
||||
<input placeholder="hostname.tld" required="required" name="host" type="text"
|
||||
value="@if($emailServer->id){{ $emailServer->host }}@else{{ old('host') }}@endif">
|
||||
<label for="host">{{ __('Hostname') }}</label>
|
||||
@include('parts.errors', ['name' => 'host'])
|
||||
</div>
|
||||
<div>
|
||||
<input placeholder="25" name="port" type="number" min="0"
|
||||
@if($emailServer->id)value="{{ $emailServer->port }}"@else value="25"@endif">
|
||||
<label for="port">{{ __('Port') }}</label>
|
||||
@include('parts.errors', ['name' => 'port'])
|
||||
</div>
|
||||
<div>
|
||||
<input placeholder="username" name="username" type="text"
|
||||
value="@if($emailServer->id){{ $emailServer->username }}@else{{ old('username') }}@endif">
|
||||
<label for="username">{{ __('Username') }}</label>
|
||||
@include('parts.errors', ['name' => 'username'])
|
||||
</div>
|
||||
<div>
|
||||
<input placeholder="password" name="password" type="text"
|
||||
value="@if($emailServer->id){{ $emailServer->password }}@else{{ old('password') }}@endif">
|
||||
<label for="password">{{ __('Password') }}</label>
|
||||
@include('parts.errors', ['name' => 'password'])
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input placeholder="username@domain.tld" name="from_address" type="email"
|
||||
value="@if($emailServer->id){{ $emailServer->from_address }}@else{{ old('from_address') }}@endif">
|
||||
<label for="from_address">{{ __('From Address') }}</label>
|
||||
@include('parts.errors', ['name' => 'from_address'])
|
||||
</div>
|
||||
<div>
|
||||
<input placeholder="John Doe" name="from_name" type="text"
|
||||
value="@if($emailServer->id){{ $emailServer->from_name }}@else{{ old('from_name') }}@endif">
|
||||
<label for="from_name">{{ __('From Name') }}</label>
|
||||
@include('parts.errors', ['name' => 'from_name'])
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<input placeholder="The Company Team" name="signature" type="text"
|
||||
value="@if($emailServer->id){{ $emailServer->signature }}@else{{ old('signature') }}@endif">
|
||||
<label for="signature">{{ __('Signature') }}</label>
|
||||
@include('parts.errors', ['name' => 'signature'])
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<br />
|
||||
|
||||
<input form="show" class="btn" type="submit" value="@if($emailServer->id){{ __('Update') }}@else{{ __('Create') }}@endif">
|
||||
@endsection
|
||||
39
flexiapi/resources/views/admin/space/integration.blade.php
Normal file
39
flexiapi/resources/views/admin/space/integration.blade.php
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
@extends('layouts.main')
|
||||
|
||||
@section('breadcrumb')
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{{ route('admin.spaces.index') }}">{{ __('Spaces') }}</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{{ route('admin.spaces.show', $space->id) }}">
|
||||
{{ $space->name }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ __('Integration') }}</li>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<header>
|
||||
<h1><i class="ph">globe-hemisphere-west</i> {{ $space->name }}</h1>
|
||||
</header>
|
||||
|
||||
@include('admin.space.tabs')
|
||||
|
||||
<div class="grid third">
|
||||
<div class="card">
|
||||
<span class="icon"><i class="ph">envelope</i></span>
|
||||
<h3>{{ __('Email Server') }}</h3>
|
||||
<p>
|
||||
@if ($space->emailServer)
|
||||
{{ $space->emailServer->host}}<br /><br />
|
||||
@endif
|
||||
@if ($space->emailServer)
|
||||
<a class="btn oppose" href="{{ route('admin.spaces.email.show', $space) }}">{{ __('Edit') }}</a>
|
||||
<a class="btn oppose btn-tertiary" href="{{ route('admin.spaces.email.delete', $space) }}">{{ __('Delete') }}</a>
|
||||
@else
|
||||
<a class="btn oppose btn-secondary" href="{{ route('admin.spaces.email.show', $space) }}">{{ __('Configure') }}</a>
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -5,8 +5,10 @@
|
|||
$items[route('admin.spaces.show', $space->id)] = __('Information');
|
||||
$items[route('admin.spaces.administration', $space->id)] = __('Administration');
|
||||
$items[route('admin.spaces.edit', $space->id)] = __('App Configuration');
|
||||
$items[route('admin.spaces.integration', $space->id)] = __('Integration');
|
||||
} else if (auth()->user()->admin) {
|
||||
$items[route('admin.spaces.me')] = __('Information');
|
||||
$items[route('admin.spaces.integration', $space->id)] = __('Integration');
|
||||
}
|
||||
|
||||
$items[route('admin.spaces.configuration', $space->id)] = __('Configuration');
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
@extends('layouts.main', ['welcome' => true])
|
||||
|
||||
@section('content')
|
||||
<div>
|
||||
{{-- This view is only a wrapper for the markdown page --}}
|
||||
{!! $documentation !!}
|
||||
</div>
|
||||
<section class="documentation">
|
||||
{{-- This view is only a wrapper for the markdown page --}}
|
||||
{!! $documentation !!}
|
||||
</section>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ A `content-type` and `accept` HTTP headers are REQUIRED to use the API properly
|
|||
> accept: application/json
|
||||
```
|
||||
|
||||
<div class="card bg-light mb-3">
|
||||
<div class="card-body">
|
||||
<div class="card">
|
||||
|
||||
Restricted endpoints are protected using a DIGEST authentication or an API Key mechanisms.
|
||||
|
||||
|
|
@ -111,7 +110,6 @@ A `from` (consisting of the user SIP address, prefixed with `sip:`) header is re
|
|||
|
||||
You can find more documentation on the related [IETF RFC-7616](https://tools.ietf.org/html/rfc7616).
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
# Endpoints
|
||||
|
|
@ -226,6 +224,31 @@ JSON parameters:
|
|||
|
||||
Delete a domain, **be careful, all the related accounts will also be destroyed**.
|
||||
|
||||
### `GET /spaces/{domain}/email`
|
||||
<span class="badge badge-error">Super Admin</span>
|
||||
|
||||
Get a space email server configuration
|
||||
|
||||
### `POST /spaces/{domain}/email`
|
||||
<span class="badge badge-error">Super Admin</span>
|
||||
|
||||
Update an existing a space email server configuration.
|
||||
|
||||
JSON parameters:
|
||||
|
||||
* `host` **required**, the email server hostname
|
||||
* `port` **required**, integer, the port
|
||||
* `username`, the username
|
||||
* `password`, the password
|
||||
* `from_address`, email address, the sender email address
|
||||
* `from_name`, the sender name
|
||||
* `signature`, a text that will end every emails sent
|
||||
|
||||
### `DELETE /spaces/{domain}/email`
|
||||
<span class="badge badge-error">Super Admin</span>
|
||||
|
||||
Delete the a space email server configuration.
|
||||
|
||||
## Account Creation Tokens
|
||||
|
||||
An `account_creation_token` is a unique token that allow the creation or the validation of a unique account.
|
||||
|
|
@ -860,7 +883,7 @@ JSON parameters:
|
|||
## Push Notifications
|
||||
|
||||
### `POST /push_notification`
|
||||
<span class="badge badge-warning">User</span>
|
||||
<span class="badge badge-info">User</span>
|
||||
|
||||
Send a push notification using the Flexisip Pusher.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
@extends('layouts.main', ['welcome' => true])
|
||||
|
||||
@section('content')
|
||||
<div>
|
||||
{{-- This view is only a wrapper for the markdown page --}}
|
||||
{!! $documentation !!}
|
||||
</div>
|
||||
<section class="documentation">
|
||||
{{-- This view is only a wrapper for the markdown page --}}
|
||||
{!! $documentation !!}
|
||||
</section>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ use App\Http\Controllers\Api\Admin\AccountTypeController;
|
|||
use App\Http\Controllers\Api\Admin\ContactsListController;
|
||||
use App\Http\Controllers\Api\Admin\ExternalAccountController;
|
||||
use App\Http\Controllers\Api\Admin\SpaceController;
|
||||
use App\Http\Controllers\Api\Admin\EmailServerController;
|
||||
use App\Http\Controllers\Api\Admin\VcardsStorageController as AdminVcardsStorageController;
|
||||
use App\Http\Controllers\Api\StatisticsMessageController;
|
||||
use App\Http\Controllers\Api\StatisticsCallController;
|
||||
|
|
@ -62,7 +63,7 @@ Route::get('accounts/me/api_key/{auth_token}', 'Api\Account\ApiKeyController@gen
|
|||
|
||||
Route::get('phone_countries', 'Api\PhoneCountryController@index');
|
||||
|
||||
Route::group(['middleware' => ['auth.jwt', 'auth.digest_or_key', 'auth.check_blocked', 'space.expired']], function () {
|
||||
Route::group(['middleware' => ['auth.jwt', 'auth.digest_or_key', 'auth.check_blocked', 'space.check']], function () {
|
||||
Route::get('accounts/auth_token/{auth_token}/attach', 'Api\Account\AuthTokenController@attach');
|
||||
Route::post('account_creation_tokens/consume', 'Api\Account\CreationTokenController@consume');
|
||||
|
||||
|
|
@ -108,6 +109,12 @@ Route::group(['middleware' => ['auth.jwt', 'auth.digest_or_key', 'auth.check_blo
|
|||
Route::put('{domain}', 'update');
|
||||
Route::delete('{domain}', 'destroy');
|
||||
});
|
||||
|
||||
Route::prefix('spaces/{domain}/email')->controller(EmailServerController::class)->group(function () {
|
||||
Route::get('/', 'show');
|
||||
Route::post('/', 'store');
|
||||
Route::delete('/', 'destroy');
|
||||
});
|
||||
});
|
||||
|
||||
// Account creation token
|
||||
|
|
|
|||
|
|
@ -41,15 +41,16 @@ use App\Http\Controllers\Admin\ContactsListContactController;
|
|||
use App\Http\Controllers\Admin\ExternalAccountController;
|
||||
use App\Http\Controllers\Admin\PhoneCountryController;
|
||||
use App\Http\Controllers\Admin\ResetPasswordEmailController;
|
||||
use App\Http\Controllers\Admin\SpaceController;
|
||||
use App\Http\Controllers\Admin\StatisticsController;
|
||||
use App\Http\Controllers\Admin\SpaceController;
|
||||
use App\Http\Controllers\Admin\Space\EmailServerController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::redirect('/', 'login')->name('account.home');
|
||||
Route::get('documentation', 'Account\AccountController@documentation')->name('account.documentation');
|
||||
Route::get('about', 'AboutController@about')->name('about');
|
||||
|
||||
Route::middleware(['web_panel_enabled', 'space.expired'])->group(function () {
|
||||
Route::middleware(['web_panel_enabled', 'space.check'])->group(function () {
|
||||
Route::get('login', 'Account\AuthenticateController@login')->name('account.login');
|
||||
Route::post('authenticate', 'Account\AuthenticateController@authenticate')->name('account.authenticate');
|
||||
Route::get('authenticate/qrcode/{token?}', 'Account\AuthenticateController@loginAuthToken')->name('account.authenticate.auth_token');
|
||||
|
|
@ -87,7 +88,7 @@ Route::name('provisioning.')->prefix('provisioning')->controller(ProvisioningCon
|
|||
Route::get('/', 'show')->name('show');
|
||||
});
|
||||
|
||||
Route::middleware(['web_panel_enabled', 'space.expired'])->group(function () {
|
||||
Route::middleware(['web_panel_enabled', 'space.check'])->group(function () {
|
||||
Route::middleware(['public_registration'])->group(function () {
|
||||
Route::redirect('register', 'register/email')->name('account.register');
|
||||
|
||||
|
|
@ -156,9 +157,19 @@ Route::middleware(['web_panel_enabled', 'space.expired'])->group(function () {
|
|||
Route::get('auth_tokens/auth/{token}', 'Account\AuthTokenController@auth')->name('auth_tokens.auth');
|
||||
|
||||
Route::name('admin.')->prefix('admin')->middleware(['auth.admin', 'auth.check_blocked'])->group(function () {
|
||||
Route::get('space', 'Admin\SpaceController@me')->name('spaces.me');
|
||||
Route::get('spaces/{space}/configuration', 'Admin\SpaceController@configuration')->name('spaces.configuration');
|
||||
Route::put('spaces/{space}/configuration', 'Admin\SpaceController@configurationUpdate')->name('spaces.configuration.update');
|
||||
Route::name('spaces.')->prefix('spaces')->group(function () {
|
||||
Route::get('me', 'Admin\SpaceController@me')->name('me');
|
||||
Route::get('{space}/configuration', 'Admin\SpaceController@configuration')->name('configuration');
|
||||
Route::put('{space}/configuration', 'Admin\SpaceController@configurationUpdate')->name('configuration.update');
|
||||
Route::get('{space}/integration', 'Admin\SpaceController@integration')->name('integration');
|
||||
|
||||
Route::name('email.')->prefix('{space}/email')->controller(EmailServerController::class)->group(function () {
|
||||
Route::get('/', 'show')->name('show');
|
||||
Route::post('/', 'store')->name('store');
|
||||
Route::get('delete', 'delete')->name('delete');
|
||||
Route::delete('/', 'destroy')->name('destroy');
|
||||
});
|
||||
});
|
||||
|
||||
Route::middleware(['auth.super_admin'])->group(function () {
|
||||
Route::resource('spaces', SpaceController::class);
|
||||
|
|
|
|||
77
flexiapi/tests/Feature/ApiSpaceEmailServerTest.php
Normal file
77
flexiapi/tests/Feature/ApiSpaceEmailServerTest.php
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
/*
|
||||
Flexisip Account Manager is a set of tools to manage SIP accounts.
|
||||
Copyright (C) 2020 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 Tests\Feature;
|
||||
|
||||
use App\Account;
|
||||
use App\Space;
|
||||
use Carbon\Carbon;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ApiSpaceEmailServerTest extends TestCase
|
||||
{
|
||||
protected $method = 'POST';
|
||||
protected $route = '/api/spaces';
|
||||
|
||||
public function testEmailServer()
|
||||
{
|
||||
$admin = Account::factory()->superAdmin()->create();
|
||||
$admin->generateApiKey();
|
||||
$emailHost = 'email.domain';
|
||||
|
||||
$route = $this->route . '/' . $admin->space->host . '/email';
|
||||
|
||||
$this->keyAuthenticated($admin)
|
||||
->json($this->method, $route, [
|
||||
'host' => $emailHost,
|
||||
'port' => 22
|
||||
])
|
||||
->assertStatus(201);
|
||||
|
||||
$this->keyAuthenticated($admin)
|
||||
->json('GET', $route)
|
||||
->assertJsonFragment([
|
||||
'host' => $emailHost,
|
||||
'port' => 22
|
||||
])
|
||||
->assertStatus(200);
|
||||
|
||||
$this->keyAuthenticated($admin)
|
||||
->json($this->method, $route, [
|
||||
'host' => $emailHost,
|
||||
'port' => 23
|
||||
])
|
||||
->assertStatus(200);
|
||||
|
||||
$this->keyAuthenticated($admin)
|
||||
->json('GET', $route)
|
||||
->assertJsonFragment([
|
||||
'port' => 23
|
||||
])
|
||||
->assertStatus(200);
|
||||
|
||||
$this->keyAuthenticated($admin)
|
||||
->json('DELETE', $route)
|
||||
->assertStatus(200);
|
||||
|
||||
$this->keyAuthenticated($admin)
|
||||
->json('GET', $route)
|
||||
->assertStatus(404);
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
namespace Tests;
|
||||
|
||||
use App\PhoneCountry;
|
||||
use App\Http\Middleware\IsSpaceExpired;
|
||||
use App\Http\Middleware\SpaceCheck;
|
||||
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ abstract class TestCase extends BaseTestCase
|
|||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->withoutMiddleware([IsSpaceExpired::class]);
|
||||
$this->withoutMiddleware([SpaceCheck::class]);
|
||||
|
||||
config()->set('app.sip_domain', 'sip.example.com');
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue