Skip to content

Commit

Permalink
implemented impersonation feature for system admin, fixed mail settin…
Browse files Browse the repository at this point in the history
…gs for smtp and added support for mailgun, sendgrid, postmark and resend, removed model cache, updated test mail message
  • Loading branch information
roncodes committed Nov 7, 2024
1 parent 1bc9d8b commit 1058dfd
Show file tree
Hide file tree
Showing 13 changed files with 218 additions and 40 deletions.
7 changes: 0 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"fleetbase/twilio": "^5.0.1",
"aws/aws-sdk-php-laravel": "^3.7",
"fleetbase/laravel-mysql-spatial": "^1.0.2",
"genealabs/laravel-model-caching": "dev-fix/handle-datetime-values",
"giggsey/libphonenumber-for-php": "^8.13",
"guzzlehttp/guzzle": "^7.4",
"hammerstone/fast-paginate": "^1.0",
Expand Down Expand Up @@ -60,12 +59,6 @@
"phpstan/phpstan": "^1.10.38",
"symfony/var-dumper": "^5.4.29"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/fleetbase/laravel-model-caching"
}
],
"autoload": {
"psr-4": {
"Fleetbase\\": "src/",
Expand Down
11 changes: 0 additions & 11 deletions config/laravel-model-caching.php

This file was deleted.

73 changes: 72 additions & 1 deletion src/Http/Controllers/Internal/v1/AuthController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Fleetbase\Exceptions\InvalidVerificationCodeException;
use Fleetbase\Http\Controllers\Controller;
use Fleetbase\Http\Requests\AdminRequest;
use Fleetbase\Http\Requests\Internal\ResetPasswordRequest;
use Fleetbase\Http\Requests\Internal\UserForgotPasswordRequest;
use Fleetbase\Http\Requests\JoinOrganizationRequest;
Expand Down Expand Up @@ -104,7 +105,12 @@ public function session(Request $request)
return response()->error('Session has expired.', 401, ['restore' => false]);
}

return response()->json(['token' => $request->bearerToken(), 'user' => $user->uuid, 'verified' => $user->isVerified(), 'type' => $user->getType()]);
$session = ['token' => $request->bearerToken(), 'user' => $user->uuid, 'verified' => $user->isVerified(), 'type' => $user->getType()];
if (session()->has('impersonator')) {
$session['impersonator'] = session()->get('impersonator');
}

return response()->json($session);
}

/**
Expand Down Expand Up @@ -676,4 +682,69 @@ public function changeUserPassword(Request $request)

return response()->json(['status' => 'ok']);
}

/**
* Allows system admin to impersonate a user.
*
* @return \Illuminate\Http\Response
*/
public function impersonate(AdminRequest $request)
{
$currentUser = Auth::getUserFromSession($request);
if ($currentUser->isNotAdmin()) {
return response()->error('Not authorized to impersonate users.');
}

$targetUserId = $request->input('user');
if (!$targetUserId) {
return response()->error('Not target user selected to impersonate.');
}

$targetUser = User::where('uuid', $targetUserId)->first();
if (!$targetUser) {
return response()->error('The selected user to impersonate was not found.');
}

try {
Auth::setSession($targetUser);
session()->put('impersonator', $currentUser->uuid);
$token = $targetUser->createToken($targetUser->uuid);
} catch (\Exception $e) {
return response()->error($e->getMessage());
}

return response()->json(['status' => 'ok', 'token' => $token->plainTextToken]);
}

/**
* Ends the impersonation session.
*
* @return \Illuminate\Http\Response
*/
public function endImpersonation()
{
$impersonatorId = session()->get('impersonator');
if (!$impersonatorId) {
return response()->error('Not impersonator session found.');
}

$impersonator = User::where('uuid', $impersonatorId)->first();
if (!$impersonator) {
return response()->error('The impersonator user was not found.');
}

if ($impersonator->isNotAdmin()) {
return response()->error('The impersonator does not have permissions. Logout.');
}

try {
Auth::setSession($impersonator);
session()->remove('impersonator');
$token = $impersonator->createToken($impersonator->uuid);
} catch (\Exception $e) {
return response()->error($e->getMessage());
}

return response()->json(['status' => 'ok', 'token' => $token->plainTextToken]);
}
}
15 changes: 15 additions & 0 deletions src/Http/Controllers/Internal/v1/CustomFieldValueController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Fleetbase\Http\Controllers\Internal\v1;

use Fleetbase\Http\Controllers\FleetbaseController;

class CustomFieldValueController extends FleetbaseController
{
/**
* The resource to query.
*
* @var string
*/
public $resource = 'custom_field_value';
}
74 changes: 62 additions & 12 deletions src/Http/Controllers/Internal/v1/SettingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Fleetbase\Support\Utils;
use Illuminate\Http\Request;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\Facades\Storage;
Expand Down Expand Up @@ -206,10 +207,14 @@ public function testFilesystemConfig(AdminRequest $request)
*/
public function getMailConfig(AdminRequest $request)
{
$mailer = config('mail.default');
$from = config('mail.from');
$mailers = array_keys(config('mail.mailers', []));
$smtpConfig = config('mail.mailers.smtp');
$mailer = config('mail.default');
$from = config('mail.from');
$mailers = Arr::except(array_keys(config('mail.mailers', [])), ['log', 'array', 'failover']);
$smtpConfig = config('mail.mailers.smtp');
$mailgunConfig = config('services.mailgun');
$postmarkConfig = config('services.postmark');
$sendgridConfig = config('services.sendgrid');
$resendConfig = config('services.resend');

$config = [
'mailer' => $mailer,
Expand All @@ -226,6 +231,22 @@ public function getMailConfig(AdminRequest $request)
$config['smtp' . ucfirst($key)] = $value;
}

foreach ($mailgunConfig as $key => $value) {
$config['mailgun' . ucfirst($key)] = $value;
}

foreach ($postmarkConfig as $key => $value) {
$config['postmark' . ucfirst($key)] = $value;
}

foreach ($sendgridConfig as $key => $value) {
$config['sendgrid' . ucfirst($key)] = $value;
}

foreach ($resendConfig as $key => $value) {
$config['resend' . ucfirst($key)] = $value;
}

return response()->json($config);
}

Expand All @@ -236,13 +257,21 @@ public function getMailConfig(AdminRequest $request)
*/
public function saveMailConfig(AdminRequest $request)
{
$mailer = $request->input('mailer', 'smtp');
$from = $request->input('from', []);
$smtp = $request->input('smtp', []);
$mailer = $request->input('mailer', 'smtp');
$from = $request->array('from', []);
$smtp = $request->array('smtp');
$mailgun = $request->array('mailgun');
$postmark = $request->array('postmark');
$sendgrid = $request->array('sendgrid');
$resend = $request->array('resend');

Setting::configureSystem('mail.mailer', $mailer);
Setting::configureSystem('mail.from', $from);
Setting::configureSystem('mail.smtp', array_merge(['transport' => 'smtp'], $smtp));
Setting::configureSystem('services.mailgun', $mailgun);
Setting::configureSystem('services.postmark', $postmark);
Setting::configureSystem('services.sendgrid', $sendgrid);
Setting::configureSystem('services.resend', $resend);

return response()->json(['status' => 'OK']);
}
Expand All @@ -268,16 +297,37 @@ public function testMailConfig(AdminRequest $request)
'name' => 'Fleetbase',
]
);
$smtp = $request->input('smtp', []);
$user = $request->user();
$message = 'Mail configuration is successful, check your inbox for the test email to confirm.';
$status = 'success';
$smtp = $request->input('smtp', []);
$mailgun = $request->array('mailgun');
$postmark = $request->array('postmark');
$sendgrid = $request->array('sendgrid');
$resend = $request->array('resend');
$user = $request->user();
$message = 'Mail configuration is successful, check your inbox for the test email to confirm.';
$status = 'success';

// set config values from input
config(['mail.default' => $mailer, 'mail.from' => $from, 'mail.mailers.smtp' => array_merge(['transport' => 'smtp'], $smtp)]);

// set mailer configs
if ($mailer === 'mailgun') {
config(['services.mailgun' => $mailgun]);
}

if ($mailer === 'postmark') {
config(['services.postmark' => $postmark]);
}

if ($mailer === 'sendgrid') {
config(['services.sendgrid' => $sendgrid]);
}

if ($mailer === 'resend') {
config(['services.resend' => $resend]);
}

try {
Mail::send(new \Fleetbase\Mail\TestMail($user));
Mail::send(new \Fleetbase\Mail\TestMail($user, $mailer));
} catch (\Aws\Ses\Exception\SesException|\Exception $e) {
$message = $e->getMessage();
$status = 'error';
Expand Down
43 changes: 43 additions & 0 deletions src/Http/Requests/Internal/BulkActionRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Fleetbase\Http\Requests\Internal;

use Fleetbase\Http\Requests\FleetbaseRequest;

class BulkActionRequest extends FleetbaseRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return $this->session()->has('user');
}

/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'ids' => ['required', 'array'],
];
}

/**
* Get the validation rules error messages.
*
* @return array
*/
public function messages()
{
return [
'ids.required' => 'Please provide a resource ID.',
'ids.array' => 'Please provide multiple resource ID\'s.',
];
}
}
11 changes: 9 additions & 2 deletions src/Mail/TestMail.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,18 @@ class TestMail extends Mailable implements ShouldQueue
*/
public User $user;

/**
* The mailer used to send the email.
*/
public string $sendingMailer;

/**
* Creates an instance of the TestMail.
*/
public function __construct(User $user)
public function __construct(User $user, string $sendingMailer = 'smtp')
{
$this->user = $user;
$this->user = $user;
$this->sendingMailer = $sendingMailer;
}

/**
Expand All @@ -54,6 +60,7 @@ public function content(): Content
markdown: 'fleetbase::mail.test',
with: [
'user' => $this->user,
'mailer' => $this->sendingMailer,
'currentHour' => now()->hour,
]
);
Expand Down
5 changes: 1 addition & 4 deletions src/Models/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use Fleetbase\Traits\HasCacheableAttributes;
use Fleetbase\Traits\Insertable;
use Fleetbase\Traits\Searchable;
use GeneaLabs\LaravelModelCaching\Traits\Cachable;
use Illuminate\Database\Eloquent\Model as EloquentModel;
use Illuminate\Database\Eloquent\SoftDeletes;

Expand All @@ -19,9 +18,7 @@ class Model extends EloquentModel
use ClearsHttpCache;
use Insertable;
use Filterable;
use Expandable, Cachable {
Expandable::__call insteadof Cachable;
}
use Expandable;

/**
* Create a new instance of the model.
Expand Down
1 change: 0 additions & 1 deletion src/Providers/CoreServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ public function register()
$this->mergeConfigFrom(__DIR__ . '/../../config/excel.php', 'excel');
$this->mergeConfigFrom(__DIR__ . '/../../config/sentry.php', 'sentry');
$this->mergeConfigFrom(__DIR__ . '/../../config/laravel-mysql-s3-backup.php', 'laravel-mysql-s3-backup');
$this->mergeConfigFrom(__DIR__ . '/../../config/laravel-model-caching.php', 'laravel-model-caching');
$this->mergeConfigFrom(__DIR__ . '/../../config/responsecache.php', 'responsecache');
}

Expand Down
10 changes: 10 additions & 0 deletions src/Support/EnvironmentMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ class EnvironmentMapper
'GOOGLE_CLOUD_STORAGE_API_URI' => 'filesystem.gcs.storage_api_uri',
'SENTRY_DSN' => 'services.sentry.dsn',
'IPINFO_API_KEY' => 'services.ipinfo.api_key',
'MAILGUN_DOMAIN' => 'services.mailgun.domain',
'MAILGUN_SECRET' => 'services.mailgun.secret',
'MAILGUN_ENDPOINT' => 'services.mailgun.endpoint',
'POSTMARK_TOKEN' => 'services.postmark.token',
'SENDGRID_API_KEY' => 'services.sendgrid.api_key',
'RESEND_KEY' => 'services.resend.key',
];

/**
Expand Down Expand Up @@ -86,6 +92,10 @@ class EnvironmentMapper
['settingsKey' => 'services.twilio', 'configKey' => 'twilio.twilio.connections.twilio'],
['settingsKey' => 'services.ipinfo', 'configKey' => 'services.ipinfo'],
['settingsKey' => 'services.ipinfo', 'configKey' => 'fleetbase.services.ipinfo'],
['settingsKey' => 'services.mailgun', 'configKey' => 'services.mailgun'],
['settingsKey' => 'services.postmark', 'configKey' => 'services.postmark'],
['settingsKey' => 'services.sendgrid', 'configKey' => 'services.sendgrid'],
['settingsKey' => 'services.resend', 'configKey' => 'services.resend'],
['settingsKey' => 'services.sentry.dsn', 'configKey' => 'sentry.dsn'],
['settingsKey' => 'broadcasting.apn', 'configKey' => 'broadcasting.connections.apn'],
['settingsKey' => 'firebase.app', 'configKey' => 'firebase.projects.app'],
Expand Down
2 changes: 1 addition & 1 deletion src/Support/Http.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public static function lookupIp($ip = null)

public static function action(?string $verb = null)
{
$verb = $verb ?? $_SERVER['REQUEST_METHOD'];
$verb = $verb ? $verb : (isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : null);
$action = Str::lower($verb);

switch ($verb) {
Expand Down
Loading

0 comments on commit 1058dfd

Please sign in to comment.