729 lines
27 KiB
PHP
729 lines
27 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace App\Http\Controllers;
|
||
|
|
||
|
use Illuminate\Support\Facades\Auth;
|
||
|
use Illuminate\Support\Facades\Storage;
|
||
|
use Illuminate\Http\Request;
|
||
|
|
||
|
use App\Account;
|
||
|
use App\Alias;
|
||
|
use App\Domain;
|
||
|
use App\DomainUser;
|
||
|
use App\TlsPolicy;
|
||
|
use App\User;
|
||
|
use App\DovecotPw;
|
||
|
use App\Entropy;
|
||
|
|
||
|
use Illuminate\Validation\ValidationException;
|
||
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||
|
use App\Exceptions\PermissionException;
|
||
|
use App\Exceptions\ErrorException;
|
||
|
use Illuminate\Validation\Rule;
|
||
|
|
||
|
|
||
|
class VMailController extends Controller
|
||
|
{
|
||
|
const MinimumEntropy = 50;
|
||
|
/**
|
||
|
* Create a new controller instance.
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
public function __construct()
|
||
|
{
|
||
|
$this->middleware('auth');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Show the application dashboard.
|
||
|
*
|
||
|
* @return \Illuminate\Contracts\Support\Renderable
|
||
|
*/
|
||
|
public function index()
|
||
|
{
|
||
|
if(Auth::user()->hasRole('admin'))
|
||
|
{
|
||
|
$domains = Domain::all();
|
||
|
return view('layouts/vmail',['domains' => $domains]);
|
||
|
}
|
||
|
elseif(Auth::user()->hasRole('user'))
|
||
|
{
|
||
|
$domains = Auth::user()->cards;
|
||
|
return view('layouts/vmail',['domains' => $domains]);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return view('layouts/unverified',);
|
||
|
}
|
||
|
|
||
|
|
||
|
return view('layouts/vmail',['domains' => $domains]);
|
||
|
}
|
||
|
|
||
|
public function domainsAjax(Request $request)
|
||
|
{
|
||
|
$action = $request->input('action');
|
||
|
try
|
||
|
{
|
||
|
// block unverified users
|
||
|
if(!(Auth::user()->hasRole('admin') || Auth::user()->hasRole('user'))){
|
||
|
throw PermissionException('Not Authorized');
|
||
|
}
|
||
|
|
||
|
if($action == 'create')
|
||
|
{
|
||
|
if(!(Auth::user()->hasRole('admin'))) { throw PermissionException('Not Authorized');}
|
||
|
|
||
|
$validatedData = $request->validate([
|
||
|
'domain' => ['required', 'string', 'unique:App\Domain,domain'],
|
||
|
]);
|
||
|
$domain = new Domain();
|
||
|
$domain->domain = $validatedData['domain'];
|
||
|
$domain->save();
|
||
|
$domain->users()->attach(Auth::user()->id,['role' => 'own']);
|
||
|
|
||
|
return [$domain];
|
||
|
}
|
||
|
elseif($action == 'rename')
|
||
|
{
|
||
|
if(!(Auth::user()->hasRole('admin'))) { throw PermissionException('Not Authorized');}
|
||
|
|
||
|
$validatedData = $request->validate([
|
||
|
'domain' => ['required', 'string', 'exists:App\Domain,domain'],
|
||
|
'newname' => ['required', 'string', 'unique:App\Domain,domain'],
|
||
|
]);
|
||
|
|
||
|
$domain = Domain::where('domain',$validatedData['domain'])->first();
|
||
|
|
||
|
$accounts = $domain->accounts;
|
||
|
$aliases = $domain->aliases;
|
||
|
$users = $domain->users;
|
||
|
|
||
|
foreach($users as $u)
|
||
|
{
|
||
|
$domain->users()->detach($u->id);
|
||
|
}
|
||
|
|
||
|
$domain->domain = $validatedData['newname'];
|
||
|
$domain->save();
|
||
|
|
||
|
foreach($accounts as $a)
|
||
|
{
|
||
|
$a->domain()->associate($domain);
|
||
|
$a->save();
|
||
|
}
|
||
|
|
||
|
foreach($aliases as $a)
|
||
|
{
|
||
|
$a->source_domain()->associate($domain);
|
||
|
$a->save();
|
||
|
}
|
||
|
|
||
|
foreach($users as $u)
|
||
|
{
|
||
|
$domain->users()->attach($u->id);
|
||
|
}
|
||
|
$domain->save();
|
||
|
|
||
|
return [$domain];
|
||
|
}
|
||
|
elseif($action == 'drop')
|
||
|
{
|
||
|
if(!(Auth::user()->hasRole('admin'))) { throw PermissionException('Not Authorized');}
|
||
|
|
||
|
$validatedData = $request->validate([
|
||
|
'domain' => ['required', 'string', 'exists:App\Domain,domain'],
|
||
|
]);
|
||
|
$domain = Domain::where('domain',$validatedData['domain'])->first();
|
||
|
|
||
|
// remove all aliases and accounts related to this domain
|
||
|
$domain->delete();
|
||
|
foreach(Account::where('domain',$validatedData['domain'])->get() as $a){
|
||
|
$a->delete();
|
||
|
}
|
||
|
foreach(Alias::where('source_domain',$validatedData['domain'])->get() as $a){
|
||
|
$a->delete();
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
elseif($action == 'listadmins')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'domain' => ['required', 'string', 'exists:App\Domain,domain'],
|
||
|
]);
|
||
|
$domain = Domain::where('domain',$validatedData['domain'])->first();
|
||
|
if(!Auth::user()->hasRole('admin')){
|
||
|
// if not an admin, check if edit roles are enabled for this domain
|
||
|
$domain->needRole('edit'); // throws exception if curren user does not have this role
|
||
|
}
|
||
|
return $domain->users;
|
||
|
|
||
|
}
|
||
|
elseif($action == 'setadmin')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'domain' => ['required', 'string', 'exists:App\Domain,domain'],
|
||
|
'userid' => ['required', 'int', 'exists:App\User,id'],
|
||
|
'role' => ['required', 'string','in:own,edit,view'],
|
||
|
]);
|
||
|
$domain = Domain::where('domain',$validatedData['domain'])->first();
|
||
|
if(!Auth::user()->hasRole('admin')){
|
||
|
// if not an admin, check if edit roles are enabled for this domain
|
||
|
$domain->needRole('own'); // throws exception if curren user does not have this role
|
||
|
|
||
|
if($validatedData['userid'] == Auth::user()->id)
|
||
|
{
|
||
|
throw ValidationException('Cannot edit own ownership');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$domain->users()->attach($validatedData['userid'],['role' => $validatedData['userid']]);
|
||
|
$domain->save();
|
||
|
|
||
|
return true;
|
||
|
|
||
|
}
|
||
|
elseif($action == 'deladmin')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'domain' => ['required', 'string', 'exists:App\Domain,domain'],
|
||
|
'userid' => ['required', 'int', 'exists:App\User,id'],
|
||
|
]);
|
||
|
$domain = Domain::where('domain',$validatedData['domain'])->first();
|
||
|
if(!Auth::user()->hasRole('admin')){
|
||
|
// if not an admin, check if edit roles are enabled for this domain
|
||
|
$domain->needRole('own'); // throws exception if curren user does not have this role
|
||
|
|
||
|
if($validatedData['userid'] == Auth::user()->id)
|
||
|
{
|
||
|
throw ValidationException('Cannot remove own ownership');
|
||
|
}
|
||
|
}
|
||
|
$domain->users()->detach($validatedData['userid']);
|
||
|
$domain->save();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
elseif($action == 'listusers')
|
||
|
{
|
||
|
$users = User::all();
|
||
|
return $users;
|
||
|
}
|
||
|
elseif($action == 'list')
|
||
|
{
|
||
|
if(Auth::user()->hasRole('admin'))
|
||
|
{
|
||
|
$domains = Domain::all();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$domains = Auth::user()->cards;
|
||
|
}
|
||
|
return $domains;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return response(['fail' => 'action', 'errors' => ['Action unknown: '. $action]],400);
|
||
|
}
|
||
|
}
|
||
|
catch(ValidationException $v)
|
||
|
{
|
||
|
return response(['fail' => 'validation', 'errors' => $v->errors()],400);
|
||
|
}
|
||
|
catch(PermissionException $x)
|
||
|
{
|
||
|
return response(['fail' => 'role', 'errors' => ['Action requires role '. $x->role()]],403);
|
||
|
}
|
||
|
catch(ErrorException $v)
|
||
|
{
|
||
|
return response(['fail' => 'errors', 'errors' => $v->errors()],400);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function tlsAjax(Request $request)
|
||
|
{
|
||
|
$action = $request->input('action');
|
||
|
try
|
||
|
{
|
||
|
// allow only admin
|
||
|
if(!(Auth::user()->hasRole('admin'))) { throw PermissionException('Not Authorized');}
|
||
|
|
||
|
|
||
|
if($action == 'list')
|
||
|
{
|
||
|
$policies = TlsPolicy::all();
|
||
|
return $policies;
|
||
|
}
|
||
|
elseif($action == 'getpolicy')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'domain' => ['required', 'string',],
|
||
|
]);
|
||
|
$domain = Domain::where('domain',$validatedData['domain'])->first();
|
||
|
$tlspolicy = $domain->tlspolicy;
|
||
|
if(empty($tlspolicy)) {
|
||
|
return ['policy' => 'null', 'params' => ''];
|
||
|
} else {
|
||
|
return $tlspolicy;
|
||
|
}
|
||
|
return response(['fail' => 'action', 'errors' => ["Unauthorized for domain '{$validatedData['domain']}'"]],403);
|
||
|
}
|
||
|
elseif($action == 'setpolicy')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'domain' => ['required', 'string', ],
|
||
|
'policy' => ['required', 'string','in:null,none,may,encrypt,dane,dane-only,fingerprint,verify,secure'],
|
||
|
'params' => ['nullable','string'],
|
||
|
]);
|
||
|
|
||
|
$tlspolicy = TlsPolicy::where('domain',$validatedData['domain'])->first();
|
||
|
if($tlspolicy == null){
|
||
|
$tlspolicy = new TlsPolicy(['domain' => $validatedData['domain'],
|
||
|
'policy' => $validatedData['policy'],
|
||
|
'params' => $validatedData['params'] ]);
|
||
|
$tlspolicy->save();
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
$tlspolicy->policy = $validatedData['policy'];
|
||
|
$tlspolicy->params = $validatedData['params'];
|
||
|
$tlspolicy->save();
|
||
|
}
|
||
|
return $tlspolicy;
|
||
|
}
|
||
|
elseif($action == 'delpolicy')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'domain' => ['required', 'string', 'exists:App\TlsPolicy,domain' ],
|
||
|
]);
|
||
|
|
||
|
$tlspolicy = TlsPolicy::where('domain',$validatedData['domain'])->first();
|
||
|
$tlspolicy->delete();
|
||
|
return true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return response(['fail' => 'action', 'errors' => ['Action unknown: '. $action]],400);
|
||
|
}
|
||
|
}
|
||
|
catch(ValidationException $v)
|
||
|
{
|
||
|
return response(['fail' => 'validation', 'errors' => $v->errors()],400);
|
||
|
}
|
||
|
catch(PermissionException $x)
|
||
|
{
|
||
|
return response(['fail' => 'role', 'errors' => ['Action requires role '. $x->role()]],403);
|
||
|
}
|
||
|
catch(ErrorException $v)
|
||
|
{
|
||
|
return response(['fail' => 'errors', 'errors' => $v->errors()],400);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function accountsAjax(Request $request)
|
||
|
{
|
||
|
$action = $request->input('action');
|
||
|
try
|
||
|
{
|
||
|
// block unverified users
|
||
|
if(!(Auth::user()->hasRole('admin') || Auth::user()->hasRole('user'))){
|
||
|
throw PermissionException('Not Authorized');
|
||
|
}
|
||
|
|
||
|
$firstValidatedData = $request->validate([
|
||
|
'domain' => ['required', 'string', 'exists:App\Domain,domain'],
|
||
|
]);
|
||
|
$domain = Domain::where('domain',$firstValidatedData['domain'])->first();
|
||
|
if(!Auth::user()->hasRole('admin')){
|
||
|
// if not an admin, check if edit roles are enabled for this domain
|
||
|
$domain->needRole('edit'); // throws exception if curren user does not have this role
|
||
|
}
|
||
|
if($action == 'create')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'username' => ['required', 'string',],
|
||
|
'enabled' => ['required', 'boolean',],
|
||
|
'sendonly' => ['required', 'boolean',],
|
||
|
'quota' => ['required', 'integer',],
|
||
|
'password' => ['required', 'string',],
|
||
|
]);
|
||
|
|
||
|
if(Account::where('username',$validatedData['username'])->where('domain', $firstValidatedData['domain'])->count() > 0){
|
||
|
throw new ValidationException('Account already exists');
|
||
|
}
|
||
|
|
||
|
// encode password
|
||
|
if(Entropy::Calculate($validatedData['password']) < static::MinimumEntropy) {
|
||
|
throw new ValidationException('Password is not complex enough');
|
||
|
}
|
||
|
$hash = DovecotPw::Encrypt($validatedData['password']);
|
||
|
|
||
|
$account = Account::Create([
|
||
|
'username' => $validatedData['username'],
|
||
|
'domain' => $firstValidatedData['domain'],
|
||
|
'enabled' => $validatedData['enabled'],
|
||
|
'sendonly' => $validatedData['sendonly'],
|
||
|
'quota' => $validatedData['quota'],
|
||
|
'password' => $hash,
|
||
|
]);
|
||
|
$account->save();
|
||
|
|
||
|
return [$account];
|
||
|
}
|
||
|
elseif($action == 'checkusername')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'username' => ['required', 'string', ''],
|
||
|
'id' => ['nullable','integer'],
|
||
|
]);
|
||
|
if(!empty($validatedData['id']))
|
||
|
{
|
||
|
$a = Account::Find($validatedData['id']);
|
||
|
if($validatedData['username'] == $a->username) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (Account::where('domain',$domain->domain)->where('username',$validatedData['username'])->count() == 0);
|
||
|
}
|
||
|
elseif($action == 'list')
|
||
|
{
|
||
|
$accounts = $domain->accounts;
|
||
|
return $accounts;
|
||
|
}
|
||
|
elseif($action == 'update')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'id' => ['required','integer'],
|
||
|
'username' => ['nullable', 'string',],
|
||
|
'enabled' => ['required', 'boolean',],
|
||
|
'sendonly' => ['required', 'boolean',],
|
||
|
'quota' => ['required', 'integer',],
|
||
|
'password' => ['nullable', 'string',],
|
||
|
]);
|
||
|
|
||
|
$account = Account::Find($validatedData['id']);
|
||
|
|
||
|
if(!empty($validatedData['username']) && $validatedData['username'] != $account->username)
|
||
|
{
|
||
|
if((Account::where('domain',$domain)->where('username',$validatedData['username'])->count()) == 0)
|
||
|
{
|
||
|
$account->username = $validatedData['username'];
|
||
|
}
|
||
|
}
|
||
|
$account->enabled = $validatedData['enabled'];
|
||
|
$account->sendonly = $validatedData['sendonly'];
|
||
|
$account->quota = $validatedData['quota'];
|
||
|
|
||
|
if(!empty($validatedData['password']))
|
||
|
{
|
||
|
if(Entropy::Calculate($validatedData['password']) < static::MinimumEntropy) {
|
||
|
throw new ValidationException('Password is not complex enough');
|
||
|
}
|
||
|
// encode password
|
||
|
$hash = DovecotPw::Encrypt($validatedData['password']);
|
||
|
$account->password = $hash;
|
||
|
}
|
||
|
$account->save();
|
||
|
|
||
|
return [$account,$hash];
|
||
|
}
|
||
|
elseif($action == 'delete')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'id' => ['required','integer'],
|
||
|
]);
|
||
|
$account = Account::Find($validatedData['id']);
|
||
|
$account->delete();
|
||
|
return [];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return response(['fail' => 'action', 'errors' => ['Action unknown: '. $action]],400);
|
||
|
}
|
||
|
}
|
||
|
catch(ValidationException $v)
|
||
|
{
|
||
|
return response(['fail' => 'validation', 'errors' => $v->errors()],400);
|
||
|
}
|
||
|
catch(PermissionException $x)
|
||
|
{
|
||
|
return response(['fail' => 'role', 'errors' => ['Action requires role '. $x->role()]],403);
|
||
|
}
|
||
|
catch(ErrorException $v)
|
||
|
{
|
||
|
return response(['fail' => 'errors', 'errors' => $v->errors()],400);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function siteAccountsAjax(Request $request)
|
||
|
{
|
||
|
$action = $request->input('action');
|
||
|
try
|
||
|
{
|
||
|
// Allow only admin
|
||
|
if(!(Auth::user()->hasRole('admin'))) { throw PermissionException('Not Authorized');}
|
||
|
|
||
|
if($action == 'create')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'username' => ['required', 'string',],
|
||
|
'enabled' => ['required', 'boolean',],
|
||
|
'sendonly' => ['required', 'boolean',],
|
||
|
'quota' => ['required', 'integer',],
|
||
|
'password' => ['required', 'string',],
|
||
|
]);
|
||
|
if(Account::where('username',$validatedData['username'])->where('domain', '')->count() > 0){
|
||
|
throw new ValidationException('Account already exists');
|
||
|
}
|
||
|
|
||
|
// encode password
|
||
|
if(Entropy::Calculate($validatedData['password']) < static::MinimumEntropy) {
|
||
|
throw new ValidationException('Password is not complex enough');
|
||
|
}
|
||
|
$hash = DovecotPw::Encrypt($validatedData['password']);
|
||
|
|
||
|
$account = Account::Create([
|
||
|
'username' => $validatedData['username'],
|
||
|
'domain' => "localhost",
|
||
|
'enabled' => $validatedData['enabled'],
|
||
|
'sendonly' => $validatedData['sendonly'],
|
||
|
'quota' => $validatedData['quota'],
|
||
|
'password' => $hash,
|
||
|
]);
|
||
|
$account->save();
|
||
|
|
||
|
return [$account];
|
||
|
}
|
||
|
elseif($action == 'checkusername')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'username' => ['required', 'string', ''],
|
||
|
'id' => ['nullable','integer'],
|
||
|
]);
|
||
|
if(!empty($validatedData['id']))
|
||
|
{
|
||
|
$a = Account::Find($validatedData['id']);
|
||
|
if($validatedData['username'] == $a->username) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (Account::where('domain',"localhost")->where('username',$validatedData['username'])->count() == 0);
|
||
|
}
|
||
|
elseif($action == 'list')
|
||
|
{
|
||
|
$accounts = Account::where('domain',"localhost")->get();
|
||
|
return $accounts;
|
||
|
}
|
||
|
elseif($action == 'update')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'id' => ['required','integer'],
|
||
|
'username' => ['nullable', 'string',],
|
||
|
'enabled' => ['required', 'boolean',],
|
||
|
'sendonly' => ['required', 'boolean',],
|
||
|
'quota' => ['required', 'integer',],
|
||
|
'password' => ['nullable', 'string',],
|
||
|
]);
|
||
|
|
||
|
$account = Account::Find($validatedData['id']);
|
||
|
|
||
|
if(!empty($validatedData['username']) && $validatedData['username'] != $account->username)
|
||
|
{
|
||
|
if((Account::where('domain',"localhost")->where('username',$validatedData['username'])->count()) == 0)
|
||
|
{
|
||
|
$account->username = $validatedData['username'];
|
||
|
}
|
||
|
}
|
||
|
$account->enabled = $validatedData['enabled'];
|
||
|
$account->sendonly = $validatedData['sendonly'];
|
||
|
$account->quota = $validatedData['quota'];
|
||
|
|
||
|
if(!empty($validatedData['password']))
|
||
|
{
|
||
|
if(Entropy::Calculate($validatedData['password']) < static::MinimumEntropy) {
|
||
|
throw new ValidationException('Password is not complex enough');
|
||
|
}
|
||
|
// encode password
|
||
|
$hash = DovecotPw::Encrypt($validatedData['password']);
|
||
|
$account->password = $hash;
|
||
|
}
|
||
|
$account->save();
|
||
|
|
||
|
return [$account,$hash];
|
||
|
}
|
||
|
elseif($action == 'delete')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'id' => ['required','integer'],
|
||
|
]);
|
||
|
$account = Account::Find($validatedData['id']);
|
||
|
$account->delete();
|
||
|
return [];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return response(['fail' => 'action', 'errors' => ['Action unknown: '. $action]],400);
|
||
|
}
|
||
|
}
|
||
|
catch(ValidationException $v)
|
||
|
{
|
||
|
return response(['fail' => 'validation', 'errors' => $v->errors()],400);
|
||
|
}
|
||
|
catch(PermissionException $x)
|
||
|
{
|
||
|
return response(['fail' => 'role', 'errors' => ['Action requires role '. $x->role()]],403);
|
||
|
}
|
||
|
catch(ErrorException $v)
|
||
|
{
|
||
|
return response(['fail' => 'errors', 'errors' => $v->errors()],400);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private function tidyAliases($aliases)
|
||
|
{
|
||
|
// figure out how to merge
|
||
|
|
||
|
$a_list = [];
|
||
|
|
||
|
foreach($aliases as $a)
|
||
|
{
|
||
|
if(empty($a_list[$a->source_username]))
|
||
|
{
|
||
|
$a_list[$a->source_username] = new \stdClass;
|
||
|
$a_list[$a->source_username]->source = $a->source_username;
|
||
|
$a_list[$a->source_username]->dest = [];
|
||
|
}
|
||
|
|
||
|
$a->destination = empty($a->destination_domain)?($a->destination_username):($a->destination_username.'@'.$a->destination_domain);
|
||
|
$a_list[$a->source_username]->dest[] = $a;
|
||
|
}
|
||
|
|
||
|
return array_values($a_list);
|
||
|
}
|
||
|
|
||
|
public function aliasesAjax(Request $request)
|
||
|
{
|
||
|
$action = $request->input('action');
|
||
|
try
|
||
|
{
|
||
|
// block unverified users
|
||
|
if(!(Auth::user()->hasRole('admin') || Auth::user()->hasRole('user'))){
|
||
|
throw PermissionException('Not Authorized');
|
||
|
}
|
||
|
|
||
|
$firstValidatedData = $request->validate([
|
||
|
'domain' => ['required', 'string', 'exists:App\Domain,domain'],
|
||
|
]);
|
||
|
$domain = Domain::where('domain',$firstValidatedData['domain'])->first();
|
||
|
if(!Auth::user()->hasRole('admin')){
|
||
|
// if not an admin, check if edit roles are enabled for this domain
|
||
|
$domain->needRole('edit'); // throws exception if curren user does not have this role
|
||
|
}
|
||
|
if($action == 'checksource')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'source' => ['required', 'string', ''],
|
||
|
'id' => ['nullable','integer'],
|
||
|
]);
|
||
|
if(!empty($validatedData['id']))
|
||
|
{
|
||
|
$a = Alias::Find($validatedData['id']);
|
||
|
if($validatedData['source_username'] == $a->source) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return (Alias::where('source_domain',$domain->domain)->where('source_username',$validatedData['source'])->count() == 0);
|
||
|
}
|
||
|
elseif($action == 'list')
|
||
|
{
|
||
|
return $this->tidyAliases($domain->aliases);
|
||
|
}
|
||
|
elseif($action == 'add_dest')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'source' => ['required','string'],
|
||
|
'destination' => ['nullable', 'string',],
|
||
|
'enabled' => ['required', 'boolean',],
|
||
|
'comment' => ['nullable', 'string',],
|
||
|
]);
|
||
|
|
||
|
$dparts = explode('@',$validatedData['destination'],2);
|
||
|
$a = Alias::Create([
|
||
|
'source_username' => $validatedData['source'],
|
||
|
'source_domain' => $domain->domain,
|
||
|
'destination_username' => $dparts[0],
|
||
|
'destination_domain' => isset($dparts[1])?$dparts[1]:null,
|
||
|
'enabled' => $validatedData['enabled'],
|
||
|
'comment' => $validatedData['comment'],
|
||
|
]);
|
||
|
$a->save();
|
||
|
|
||
|
return $this->tidyAliases([$a]);
|
||
|
}
|
||
|
elseif($action == 'update_dest')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'id' => ['required','integer'],
|
||
|
'destination' => ['nullable', 'string',],
|
||
|
'enabled' => ['required', 'boolean',],
|
||
|
'comment' => ['nullable', 'string',],
|
||
|
]);
|
||
|
|
||
|
$a = Alias::Find($validatedData['id']);
|
||
|
|
||
|
$dparts = explode('@',$validatedData['destination'],2);
|
||
|
$a->destination_username = $dparts[0];
|
||
|
$a->destination_domain = isset($dparts[1])?$dparts[1]:null;
|
||
|
$a->enabled = $validatedData['enabled'];
|
||
|
$a->comment = $validatedData['comment'];
|
||
|
|
||
|
$a->save();
|
||
|
|
||
|
return $this->tidyAliases([$a]);
|
||
|
}
|
||
|
elseif($action == 'delete_dest')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'id' => ['required','integer'],
|
||
|
]);
|
||
|
$a = Alias::Find($validatedData['id']);
|
||
|
$a->delete();
|
||
|
return [];
|
||
|
}
|
||
|
elseif($action == 'delete_src')
|
||
|
{
|
||
|
$validatedData = $request->validate([
|
||
|
'source' => ['required','string'],
|
||
|
]);
|
||
|
$aliases = Alias::where('source_domain',$domain->domain)->where('source_username',$validatedData['source']);
|
||
|
foreach($aliases as $a)
|
||
|
{
|
||
|
$a->delete();
|
||
|
}
|
||
|
return [];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return response(['fail' => 'action', 'errors' => ['Action unknown: '. $action]],400);
|
||
|
}
|
||
|
}
|
||
|
catch(ValidationException $v)
|
||
|
{
|
||
|
return response(['fail' => 'validation', 'errors' => $v->errors()],400);
|
||
|
}
|
||
|
catch(PermissionException $x)
|
||
|
{
|
||
|
return response(['fail' => 'role', 'errors' => ['Action requires role '. $x->role()]],403);
|
||
|
}
|
||
|
catch(ErrorException $v)
|
||
|
{
|
||
|
return response(['fail' => 'errors', 'errors' => $v->errors()],400);
|
||
|
}
|
||
|
}
|
||
|
}
|