shell bypass 403
<?php namespace App\Http\Controllers\Admin; use App\Exceptions\GeneralException; use App\Http\Requests\Customer\AddUnitRequest; use App\Http\Requests\Customer\PermissionRequest; use App\Http\Requests\Customer\StoreCustomerRequest; use App\Http\Requests\Customer\UpdateAvatarRequest; use App\Http\Requests\Customer\UpdateCustomerRequest; use App\Http\Requests\Customer\UpdateInformationRequest; use App\Library\Tool; use App\Models\Blacklists; use App\Models\Campaigns; use App\Models\ChatBox; use App\Models\ContactGroups; use App\Models\Customer; use App\Models\Invoices; use App\Models\Keywords; use App\Models\Language; use App\Models\Notifications; use App\Models\PhoneNumbers; use App\Models\Plan; use App\Models\Reports; use App\Models\Senderid; use App\Models\SendingServer; use App\Models\Subscription; use App\Models\SubscriptionTransaction; use App\Models\Templates; use App\Models\User; use App\Repositories\Contracts\CustomerRepository; use Box\Spout\Common\Exception\InvalidArgumentException; use Box\Spout\Common\Exception\IOException; use Box\Spout\Common\Exception\UnsupportedTypeException; use Box\Spout\Writer\Exception\WriterNotOpenedException; use Exception; use Generator; use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\View\Factory; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Http\JsonResponse; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\View\View; use Intervention\Image\Exception\NotReadableException; use Intervention\Image\Facades\Image; use JetBrains\PhpStorm\NoReturn; use Rap2hpoutre\FastExcel\FastExcel; use Symfony\Component\HttpFoundation\BinaryFileResponse; class CustomerController extends AdminBaseController { /** * @var CustomerRepository */ protected CustomerRepository $customers; /** * Create a new controller instance. * * @param CustomerRepository $customers */ public function __construct(CustomerRepository $customers) { $this->customers = $customers; } /** * @return Application|Factory|View * @throws AuthorizationException */ public function index(): Factory|View|Application { $this->authorize('view customer'); $breadcrumbs = [ ['link' => url(config('app.admin_path')."/dashboard"), 'name' => __('locale.menu.Dashboard')], ['link' => url(config('app.admin_path')."/dashboard"), 'name' => __('locale.menu.Customer')], ['name' => __('locale.menu.Customers')], ]; return view('admin.customer.index', compact('breadcrumbs')); } /** * view all customers * * @param Request $request * * @return void * @throws AuthorizationException */ #[NoReturn] public function search(Request $request): void { $this->authorize('view customer'); $columns = [ 0 => 'responsive_id', 1 => 'uid', 2 => 'uid', 3 => 'name', 4 => 'subscription', 5 => 'status', 6 => 'actions', ]; $totalData = User::where('is_customer', 1)->count(); $totalFiltered = $totalData; $limit = $request->input('length'); $start = $request->input('start'); $order = $columns[$request->input('order.0.column')]; $dir = $request->input('order.0.dir'); if (empty($request->input('search.value'))) { $users = User::where('is_customer', 1)->offset($start) ->limit($limit) ->orderBy($order, $dir) ->get(); } else { $search = $request->input('search.value'); $users = User::where('is_customer', 1)->whereLike(['uid', 'first_name', 'last_name', 'status', 'email'], $search) ->offset($start) ->limit($limit) ->orderBy($order, $dir) ->get(); $totalFiltered = User::where('is_customer', 1)->whereLike(['uid', 'first_name', 'last_name', 'status', 'email'], $search)->count(); } $data = []; if ( ! empty($users)) { foreach ($users as $user) { $show = route('admin.customers.show', $user->uid); $assign_plan = route('admin.subscriptions.create', ['customer_id' => $user->id]); $login_as = route('admin.customers.login_as', $user->uid); $assign_plan_label = __('locale.customer.assign_plan'); $login_as_label = __('locale.customer.login_as_customer'); $edit = __('locale.buttons.edit'); $delete = __('locale.buttons.delete'); if ($user->status === true) { $status = 'checked'; } else { $status = ''; } if ($user->customer->currentPlanName()) { $subscription = $user->customer->currentPlanName(); } else { $subscription = __('locale.subscription.no_active_subscription'); } $super_user = true; if ($user->id != 1) { $super_user = false; } $nestedData['responsive_id'] = ''; $nestedData['uid'] = $user->uid; $nestedData['avatar'] = route('admin.customers.avatar', $user->uid); $nestedData['email'] = $user->email; $nestedData['name'] = $user->first_name.' '.$user->last_name; $nestedData['created_at'] = __('locale.labels.created_at').': '.Tool::formatDate($user->created_at); $nestedData['subscription'] = "<div> <p class='text-bold-600'>$subscription </p> </div>"; $nestedData['status'] = "<div class='form-check form-switch form-check-primary'> <input type='checkbox' class='form-check-input get_status' id='status_$user->uid' data-id='$user->uid' name='status' $status> <label class='form-check-label' for='status_$user->uid'> <span class='switch-icon-left'><i data-feather='check'></i> </span> <span class='switch-icon-right'><i data-feather='x'></i> </span> </label> </div>"; $nestedData['assign_plan'] = $assign_plan; $nestedData['assign_plan_label'] = $assign_plan_label; $nestedData['login_as'] = $login_as; $nestedData['login_as_label'] = $login_as_label; $nestedData['show'] = $show; $nestedData['show_label'] = $edit; $nestedData['delete'] = $user->uid; $nestedData['delete_label'] = $delete; $nestedData['super_user'] = $super_user; $data[] = $nestedData; } } $json_data = [ "draw" => intval($request->input('draw')), "recordsTotal" => intval($totalData), "recordsFiltered" => intval($totalFiltered), "data" => $data, ]; echo json_encode($json_data); exit(); } /** * create new customer * * @return Application|Factory|View * @throws AuthorizationException */ public function create(): Factory|View|Application { $this->authorize('create customer'); $breadcrumbs = [ ['link' => url(config('app.admin_path')."/dashboard"), 'name' => __('locale.menu.Dashboard')], ['link' => url(config('app.admin_path')."/customers"), 'name' => __('locale.menu.Customers')], ['name' => __('locale.customer.add_new')], ]; $languages = Language::where('status', 1)->get(); return view('admin.customer.create', compact('breadcrumbs', 'languages')); } /** * * add new customer * * @param StoreCustomerRequest $request * * @return RedirectResponse */ public function store(StoreCustomerRequest $request): RedirectResponse { if (config('app.stage') == 'demo') { return redirect()->route('admin.customers.index')->with([ 'status' => 'error', 'message' => 'Sorry! This option is not available in demo mode', ]); } $customer = $this->customers->store($request->input()); // Upload and save image if ($request->hasFile('image')) { if ($request->file('image')->isValid()) { $customer->image = $customer->uploadImage($request->file('image')); $customer->save(); } } return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'success', 'message' => __('locale.customer.customer_successfully_added'), ]); } /** * View customer for edit * * @param User $customer * * @return Application|Factory|View * * @throws AuthorizationException */ public function show(User $customer): Factory|View|Application { $this->authorize('edit customer'); $breadcrumbs = [ ['link' => url(config('app.admin_path')."/dashboard"), 'name' => __('locale.menu.Dashboard')], ['link' => url(config('app.admin_path')."/customers"), 'name' => __('locale.menu.Customers')], ['name' => $customer->displayName()], ]; $languages = Language::where('status', 1)->get(); $categories = collect(config('customer-permissions'))->map(function ($value, $key) { $value['name'] = $key; return $value; })->groupBy('category'); $permissions = $categories->keys()->map(function ($key) use ($categories) { return [ 'title' => $key, 'permissions' => $categories[$key], ]; }); $existing_permission = json_decode($customer->customer->permissions, true); return view('admin.customer.show', compact('breadcrumbs', 'customer', 'languages', 'permissions', 'existing_permission')); } /** * get customer avatar * * @param User $customer * * @return mixed */ public function avatar(User $customer): mixed { if ( ! empty($customer->imagePath())) { try { $image = Image::make($customer->imagePath()); } catch (NotReadableException $exception) { $customer->image = null; $customer->save(); $image = Image::make(public_path('images/profile/profile.jpg')); } } else { $image = Image::make(public_path('images/profile/profile.jpg')); } return $image->response(); } /** * update avatar * * @param User $customer * @param UpdateAvatarRequest $request * * @return RedirectResponse */ public function updateAvatar(User $customer, UpdateAvatarRequest $request): RedirectResponse { if (config('app.stage') == 'demo') { return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'error', 'message' => 'Sorry! This option is not available in demo mode', ]); } try { // Upload and save image if ($request->hasFile('image')) { if ($request->file('image')->isValid()) { // Remove old images $customer->removeImage(); $customer->image = $customer->uploadImage($request->file('image')); $customer->save(); return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'success', 'message' => __('locale.customer.avatar_update_successful'), ]); } return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'error', 'message' => __('locale.exceptions.invalid_image'), ]); } return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'error', 'message' => __('locale.exceptions.invalid_image'), ]); } catch (Exception $exception) { return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'error', 'message' => $exception->getMessage(), ]); } } /** * remove avatar * * @param User $customer * * @return JsonResponse */ public function removeAvatar(User $customer): JsonResponse { if (config('app.stage') == 'demo') { return response()->json([ 'status' => 'error', 'message' => 'Sorry! This option is not available in demo mode', ]); } // Remove old images $customer->removeImage(); $customer->image = null; $customer->save(); return response()->json([ 'status' => 'success', 'message' => __('locale.customer.avatar_remove_successful'), ]); } /** * update customer basic account information * * @param User $customer * @param UpdateCustomerRequest $request * * @return RedirectResponse */ public function update(User $customer, UpdateCustomerRequest $request): RedirectResponse { if (config('app.stage') == 'demo') { return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'error', 'message' => 'Sorry! This option is not available in demo mode', ]); } $this->customers->update($customer, $request->input()); return redirect()->route('admin.customers.show', $customer->uid)->withInput(['tab' => 'account'])->with([ 'status' => 'success', 'message' => __('locale.customer.customer_successfully_updated'), ]); } /** * update customer detail information * * @param User $customer * @param UpdateInformationRequest $request * * @return RedirectResponse */ public function updateInformation(User $customer, UpdateInformationRequest $request): RedirectResponse { if (config('app.stage') == 'demo') { return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'error', 'message' => 'Sorry! This option is not available in demo mode', ]); } $this->customers->updateInformation($customer, $request->except('_token')); return redirect()->route('admin.customers.show', $customer->uid)->withInput(['tab' => 'information'])->with([ 'status' => 'success', 'message' => __('locale.customer.customer_successfully_updated'), ]); } /** * update user permission * * @param User $customer * @param PermissionRequest $request * * @return RedirectResponse */ public function permissions(User $customer, PermissionRequest $request): RedirectResponse { if (config('app.stage') == 'demo') { return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'error', 'message' => 'Sorry! This option is not available in demo mode', ]); } $this->customers->permissions($customer, $request->only('permissions')); return redirect()->route('admin.customers.show', $customer->uid)->withInput(['tab' => 'permission'])->with([ 'status' => 'success', 'message' => __('locale.customer.customer_successfully_updated'), ]); } /** * change customer status * * @param User $customer * * @return JsonResponse * @throws AuthorizationException * @throws GeneralException */ public function activeToggle(User $customer): JsonResponse { if (config('app.stage') == 'demo') { return response()->json([ 'status' => 'error', 'message' => 'Sorry! This option is not available in demo mode', ]); } try { $this->authorize('edit customer'); if ($customer->update(['status' => ! $customer->status])) { return response()->json([ 'status' => 'success', 'message' => __('locale.customer.customer_successfully_change'), ]); } throw new GeneralException(__('locale.exceptions.something_went_wrong')); } catch (ModelNotFoundException $exception) { return response()->json([ 'status' => 'error', 'message' => $exception->getMessage(), ]); } } /** * Bulk Action with Enable, Disable * * @param Request $request * * @return JsonResponse * @throws AuthorizationException */ public function batchAction(Request $request): JsonResponse { if (config('app.stage') == 'demo') { return response()->json([ 'status' => 'error', 'message' => 'Sorry! This option is not available in demo mode', ]); } $action = $request->get('action'); $ids = $request->get('ids'); switch ($action) { case 'enable': $this->authorize('edit customer'); $this->customers->batchEnable($ids); return response()->json([ 'status' => 'success', 'message' => __('locale.customer.customers_enabled'), ]); case 'disable': $this->authorize('edit customer'); $this->customers->batchDisable($ids); return response()->json([ 'status' => 'success', 'message' => __('locale.customer.customers_disabled'), ]); } return response()->json([ 'status' => 'error', 'message' => __('locale.exceptions.invalid_action'), ]); } /** * destroy customer * * @param User $customer * * @return JsonResponse * @throws AuthorizationException * @throws Exception */ public function destroy(User $customer): JsonResponse { if (config('app.stage') == 'demo') { return response()->json([ 'status' => 'error', 'message' => 'Sorry! This option is not available in demo mode', ]); } $this->authorize('delete customer'); PhoneNumbers::where('user_id', $customer->id)->update([ 'status' => 'available', 'user_id' => 1, ]); Blacklists::where('user_id', $customer->id)->delete(); Campaigns::where('user_id', $customer->id)->delete(); ChatBox::where('user_id', $customer->id)->delete(); ContactGroups::where('customer_id', $customer->id)->delete(); Customer::where('user_id', $customer->id)->delete(); Invoices::where('user_id', $customer->id)->delete(); Keywords::where('user_id', $customer->id)->delete(); Notifications::where('user_id', $customer->id)->delete(); Plan::where('user_id', $customer->id)->delete(); Reports::where('user_id', $customer->id)->delete(); Senderid::where('user_id', $customer->id)->delete(); SendingServer::where('user_id', $customer->id)->delete(); Subscription::where('user_id', $customer->id)->delete(); Templates::where('user_id', $customer->id)->delete(); if ( ! $customer->delete()) { return response()->json([ 'status' => 'error', 'message' => __('locale.exceptions.something_went_wrong'), ]); } return response()->json([ 'status' => 'success', 'message' => __('locale.customer.customer_successfully_deleted'), ]); } /** * @return Generator */ public function customerGenerator(): Generator { foreach (User::where('is_customer', 1)->join('customers', 'user_id', '=', 'users.id')->cursor() as $customer) { yield $customer; } } /** * @return RedirectResponse|BinaryFileResponse * @throws AuthorizationException * @throws IOException * @throws InvalidArgumentException * @throws UnsupportedTypeException * @throws WriterNotOpenedException */ public function export(): BinaryFileResponse|RedirectResponse { if (config('app.stage') == 'demo') { return redirect()->route('admin.customers.index')->with([ 'status' => 'error', 'message' => 'Sorry! This option is not available in demo mode', ]); } $this->authorize('edit customer'); $file_name = (new FastExcel($this->customerGenerator()))->export(storage_path('Customers_'.time().'.xlsx')); return response()->download($file_name); } /** * add custom unit * * @param User $customer * @param AddUnitRequest $request * * @return RedirectResponse * @throws GeneralException */ public function addUnit(User $customer, AddUnitRequest $request): RedirectResponse { if (config('app.stage') == 'demo') { return redirect()->route('admin.customers.index')->with([ 'status' => 'error', 'message' => 'Sorry! This option is not available in demo mode', ]); } try { if ($customer->sms_unit != '-1') { $balance = $customer->sms_unit + $request->add_unit; if ($customer->update(['sms_unit' => $balance])) { $subscription = $customer->customer->activeSubscription(); $subscription->addTransaction(SubscriptionTransaction::TYPE_SUBSCRIBE, [ 'end_at' => $subscription->end_at, 'current_period_ends_at' => $subscription->current_period_ends_at, 'status' => SubscriptionTransaction::STATUS_SUCCESS, 'title' => 'Add '.$request->add_unit.' sms units', 'amount' => $request->add_unit.' sms units', ]); return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'success', 'message' => __('locale.customer.add_unit_successful'), ]); } throw new GeneralException(__('locale.exceptions.something_went_wrong')); } return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'info', 'message' => 'You are already in unlimited plan', ]); } catch (ModelNotFoundException $exception) { return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'error', 'message' => $exception->getMessage(), ]); } } /** * remove custom unit * * @param User $customer * @param AddUnitRequest $request * * @return RedirectResponse * @throws GeneralException */ public function removeUnit(User $customer, AddUnitRequest $request): RedirectResponse { if (config('app.stage') == 'demo') { return redirect()->route('admin.customers.index')->with([ 'status' => 'error', 'message' => 'Sorry! This option is not available in demo mode', ]); } try { if ($customer->sms_unit != '-1') { $balance = $customer->sms_unit - $request->add_unit; if ($balance < 0) { return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'error', 'message' => 'Sorry! You can remove maximum '.$customer->sms_unit.' unit', ]); } if ($customer->update(['sms_unit' => $balance])) { $subscription = $customer->customer->activeSubscription(); $subscription->addTransaction(SubscriptionTransaction::TYPE_SUBSCRIBE, [ 'end_at' => $subscription->end_at, 'current_period_ends_at' => $subscription->current_period_ends_at, 'status' => SubscriptionTransaction::STATUS_SUCCESS, 'title' => 'Remove '.$request->add_unit.' sms units', 'amount' => $request->add_unit.' sms units', ]); return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'success', 'message' => __('locale.customer.add_unit_successful'), ]); } throw new GeneralException(__('locale.exceptions.something_went_wrong')); } return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'info', 'message' => 'You are already in unlimited plan', ]); } catch (ModelNotFoundException $exception) { return redirect()->route('admin.customers.show', $customer->uid)->with([ 'status' => 'error', 'message' => $exception->getMessage(), ]); } } /* |-------------------------------------------------------------------------- | Version 3.3 |-------------------------------------------------------------------------- | | Logged in as a customer option | */ /** * @param User $customer * * @return mixed * @throws AuthorizationException */ public function impersonate(User $customer): mixed { $this->authorize('edit customer'); return $this->customers->impersonate($customer); } }