LaravelDaily / laravel-invoices

Laravel package to generate PDF invoices from various customizable parameters

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

file_exists(): open_basedir restriction in effect

MrMooky opened this issue · comments

Running this locally works fine and the invoices are stored into the path I provided. On the production server however, I am getting this error:

file_exists(): open_basedir restriction in effect. File(/dev/null) is not within the allowed path(s)

This is the filesystem config:

'invoices' => [
    'driver' => 'local',
    'root' => storage_path('app/invoices'),
    'url' => env('APP_URL').'/invoices',
    'visibility' => 'private',
    'throw' => false,
],

open_basedir is defined as /home/xxx/webapps/xxx-xxx:/var/lib/php/session:/tmp and it is advised not to change this.

Now I wonder why this error is thrown, as the save() method basically states Storage::disk($this->disk)->put($this->filename, $this->output);, nothing fancy it seems.

I'm not sure if this is a bug, but generally storing files is not an issue with the project, only the invoices.

Update: just tried to store them directly on S3, so not even on the same server, but got the same error.

What "Running this" means? Could you provide more details about what you're doing and what happens after?

"Running this" means creating an invoice. This is the code that I use to create it:

try {
    $invoice = Invoice::make()
        ->seller($seller)
        ->buyer($buyer)
        ->discountByPercent($discountByPercent)
        ->date(now())
        ->dateFormat('Y-m-d')
        ->currencySymbol($workspace->currency_symbol)
        ->currencyCode($workspace->currency)
        ->currencyFormat('{SYMBOL}{VALUE}')
        ->currencyThousandsSeparator('.')
        ->currencyDecimalPoint(',')
        ->addItems($paymentItems->toArray())
        ->notes($workspace->invoice_note ?? '')
        ->logo(public_path('images/logo-invoices.png'))
        ->taxRate($workspace->taxrate)
        ->series(substr(now()->year, 2).''.now()->month)
        ->sequence($sequence)
        ->delimiter('-')
        ->sequencePadding(2)
        ->serialNumberFormat('{SERIES}{DELIMITER}{SEQUENCE}')
        ->filename($filename)
        ->setCustomData([
            'formName' => $payment->form->name,
            'couponName' => $payment->coupon_id ? Coupon::where('id', $payment->coupon_id)->value('name') : null,
        ])
        ->save('invoices');
} catch (\Exception $e) {
    Log::error($e->getMessage());

    return false;
}

@MrMooky do you use shared hosting? If it works locally but not on the server, this indicates there's an issue with the server configuration.

Also, try flushing config caches.

I'm using a vServer from Hetzner. At some point file_exists is called, causing the issue. As stated in my initial post, open_basedir is defined as /home/xxx/webapps/xxx-xxx:/var/lib/php/session:/tmp and it is advised not to change this because of security reasons. That is not directly an issue with server configuration.

It seems I will have to remove the package and use Browsershot, worked just fine in another project but your package was simpler to setup and use. Well... ._.

@MrMooky open_basedir restricts paths that your PHP application can access: https://www.php.net/manual/en/ini.core.php#ini.open-basedir so you might want to configure different path for invoices to be stored, the one that is defined in open_basedir.

That said, this is directly the issue with specific server configuration.

However, Browsershot does completely different thing, although you may achieve similar end result.

... so you might want to configure different path for invoices to be stored, the one that is defined in open_basedir.

The error message states File(/dev/null) is not within the allowed path(s). open_basedir has access to the webapp the platform it runs (see initial post) and it should not have access to anything else, which is the correct setup.

Well yeah, with Browsershot I'd need to build the whole invoicing logic myself but the issue here is that the invoice is not stored correctly. That is the only thing that is not working, otherwise the package does what it says.

@MrMooky alternatively you can extend invoice class and implement your own save method to meet your server's needs. You can render pdf using render method.

https://github.com/LaravelDaily/laravel-invoices/blob/master/src/Invoice.php#L264C23-L264C23

$invoice->render();

Then access contents using $invoice->output, and save it the way you want.

In case someone else stumbles upon this and lands here... The issue was caused by DomPDF: dompdf/dompdf#2810

In my case I had to add /dev/null to open_basedir as this is the default setting in https://github.com/LaravelDaily/laravel-invoices/blob/master/config/invoices.php#L113

I didn't know about /dev/null basically being the "trash can" in Linux so the initial error message did not make sense to me. The problem is solved now.

@MrMooky glad to hear it, great :)