diff --git a/app/Http/Controllers/V1/Admin/Expense/ExpensesController.php b/app/Http/Controllers/V1/Admin/Expense/ExpensesController.php index bcb94003..9027a1f4 100644 --- a/app/Http/Controllers/V1/Admin/Expense/ExpensesController.php +++ b/app/Http/Controllers/V1/Admin/Expense/ExpensesController.php @@ -39,7 +39,7 @@ class ExpensesController extends Controller /** * Store a newly created resource in storage. * - * @param \Illuminate\Http\Request $request + * @param \Crater\Http\Requests\ExpenseRequest $request * @return \Illuminate\Http\JsonResponse */ public function store(ExpenseRequest $request) @@ -67,7 +67,7 @@ class ExpensesController extends Controller /** * Update the specified resource in storage. * - * @param \Illuminate\Http\Request $request + * @param \Crater\Http\Requests\ExpenseRequest $request * @param \Crater\Models\Expense $expense * @return \Illuminate\Http\JsonResponse */ diff --git a/app/Http/Controllers/V1/Admin/Expense/UploadReceiptController.php b/app/Http/Controllers/V1/Admin/Expense/UploadReceiptController.php index cc7d6135..9c58d328 100644 --- a/app/Http/Controllers/V1/Admin/Expense/UploadReceiptController.php +++ b/app/Http/Controllers/V1/Admin/Expense/UploadReceiptController.php @@ -5,17 +5,18 @@ namespace Crater\Http\Controllers\V1\Admin\Expense; use Crater\Http\Controllers\Controller; use Crater\Models\Expense; use Illuminate\Http\Request; +use Crater\Http\Requests\ExpenseRequest; class UploadReceiptController extends Controller { /** * Upload the expense receipts to storage. * - * @param \Illuminate\Http\Request $request + * @param \Crater\Http\Requests\ExpenseRequest $request * @param Expense $expense * @return \Illuminate\Http\JsonResponse */ - public function __invoke(Request $request, Expense $expense) + public function __invoke(ExpenseRequest $request, Expense $expense) { $this->authorize('update', $expense); diff --git a/app/Http/Controllers/V1/Admin/Settings/CompanyController.php b/app/Http/Controllers/V1/Admin/Settings/CompanyController.php index f594e13b..e299c76a 100644 --- a/app/Http/Controllers/V1/Admin/Settings/CompanyController.php +++ b/app/Http/Controllers/V1/Admin/Settings/CompanyController.php @@ -9,6 +9,8 @@ use Crater\Http\Resources\CompanyResource; use Crater\Http\Resources\UserResource; use Crater\Models\Company; use Illuminate\Http\Request; +use Crater\Http\Requests\AvatarRequest; +use Crater\Http\Requests\CompanyLogoRequest; class CompanyController extends Controller { @@ -58,10 +60,10 @@ class CompanyController extends Controller /** * Upload the company logo to storage. * - * @param \Illuminate\Http\Request $request + * @param \Crater\Http\Requests\CompanyLogoRequest $request * @return \Illuminate\Http\JsonResponse */ - public function uploadCompanyLogo(Request $request) + public function uploadCompanyLogo(CompanyLogoRequest $request) { $company = Company::find($request->header('company')); @@ -89,10 +91,10 @@ class CompanyController extends Controller /** * Upload the Admin Avatar to public storage. * - * @param \Illuminate\Http\Request $request + * @param \Crater\Http\Requests\AvatarRequest $request * @return \Illuminate\Http\JsonResponse */ - public function uploadAvatar(Request $request) + public function uploadAvatar(AvatarRequest $request) { $user = auth()->user(); diff --git a/app/Http/Requests/AvatarRequest.php b/app/Http/Requests/AvatarRequest.php new file mode 100644 index 00000000..832a0ed7 --- /dev/null +++ b/app/Http/Requests/AvatarRequest.php @@ -0,0 +1,40 @@ + [ + 'nullable', + 'file', + 'mimes:gif,jpg,png', + 'max:20000' + ], + 'avatar' => [ + 'nullable', + new Base64Mime(['gif', 'jpg', 'png']) + ] + ]; + } +} diff --git a/app/Http/Requests/CompanyLogoRequest.php b/app/Http/Requests/CompanyLogoRequest.php new file mode 100644 index 00000000..3ff0c685 --- /dev/null +++ b/app/Http/Requests/CompanyLogoRequest.php @@ -0,0 +1,34 @@ + [ + 'nullable', + new Base64Mime(['gif', 'jpg', 'png']) + ] + ]; + } +} diff --git a/app/Http/Requests/ExpenseRequest.php b/app/Http/Requests/ExpenseRequest.php index b74f9be1..a8baa723 100644 --- a/app/Http/Requests/ExpenseRequest.php +++ b/app/Http/Requests/ExpenseRequest.php @@ -51,6 +51,12 @@ class ExpenseRequest extends FormRequest 'currency_id' => [ 'required' ], + 'attachment_receipt' => [ + 'nullable', + 'file', + 'mimes:jpg,png,pdf,doc,docx,xls,xlsx,ppt,pptx', + 'max:20000' + ] ]; if ($companyCurrency && $this->currency_id) { diff --git a/app/Rules/Base64Mime.php b/app/Rules/Base64Mime.php new file mode 100644 index 00000000..bb020e78 --- /dev/null +++ b/app/Rules/Base64Mime.php @@ -0,0 +1,85 @@ +extensions = $extensions; + } + + /** + * Determine if the validation rule passes. + * + * @param string $attribute + * @param mixed $value + * @return bool + */ + public function passes($attribute, $value) + { + $this->attribute = $attribute; + + try { + $data = json_decode($value)->data; + } catch (\Exception $e) { + return False; + } + + $pattern = '/^data:\w+\/[\w\+]+;base64,[\w\+\=\/]+$/'; + + if(!preg_match($pattern, $data)) { + return False; + } + + $data = explode(',', $data); + + if(!isset($data[1]) || empty($data[1])) { + return False; + } + + try { + $data = base64_decode($data[1]); + $f = finfo_open(); + $result = finfo_buffer($f, $data, FILEINFO_EXTENSION); + + if($result === '???') + return False; + + if(strpos($result, '/')) { + foreach(explode('/', $result) as $ext) { + if(in_array($ext, $this->extensions)) + return True; + } + } else { + if(in_array($result, $this->extensions)) + return True; + } + } catch (\Exception $e) { + return False; + } + + return False; + + } + + /** + * Get the validation error message. + * + * @return string + */ + public function message() + { + return 'The ' . $this->attribute . ' must be a json with file of type: ' . implode(', ', $this->extensions) . ' encoded in base64.'; + } +} diff --git a/readme.md b/readme.md index 45be8ec8..06700132 100644 --- a/readme.md +++ b/readme.md @@ -55,6 +55,8 @@ Join the Crater discord server to discuss: - [x] Multiple Companies - [x] Recurring Invoices - [ ] Modules +- [ ] Blockchain Integration +- [ ] Web 3.0 Accounting - [ ] White Labeling (Easy Invoice, Email & Consumer Portal Theme customisation) - [ ] Vendors, Inventory & Bills - [ ] Payment Reminders diff --git a/resources/scripts/components/dropdowns/InvoiceIndexDropdown.vue b/resources/scripts/components/dropdowns/InvoiceIndexDropdown.vue old mode 100644 new mode 100755 index 28744cbe..ebeab9ca --- a/resources/scripts/components/dropdowns/InvoiceIndexDropdown.vue +++ b/resources/scripts/components/dropdowns/InvoiceIndexDropdown.vue @@ -153,7 +153,6 @@ const utils = inject('utils') function canReSendInvoice(row) { return ( (row.status == 'SENT' || row.status == 'VIEWED') && - route.name !== 'invoices.view' && userStore.hasAbilities(abilities.SEND_INVOICE) ) }