diff --git a/.env.example b/.env.example index 9901b58f1475..4e5111f6f60d 100644 --- a/.env.example +++ b/.env.example @@ -39,6 +39,8 @@ MAIL_PORT=2525 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS='user@example.com' +MAIL_FROM_NAME='Self Hosted User' POSTMARK_API_TOKEN= @@ -46,4 +48,5 @@ GOOGLE_MAPS_API_KEY= API_SECRET=superdoopersecrethere ERROR_EMAIL= -NINJA_ENVIRONMENT=selfhost \ No newline at end of file +NINJA_ENVIRONMENT=selfhost +HASH_SALT= \ No newline at end of file diff --git a/app/Console/Commands/ImportMigrations.php b/app/Console/Commands/ImportMigrations.php index be032ddeacb1..5683f594f963 100644 --- a/app/Console/Commands/ImportMigrations.php +++ b/app/Console/Commands/ImportMigrations.php @@ -9,7 +9,6 @@ use App\Models\Company; use App\Models\CompanyToken; use App\Models\User; use App\Utils\Traits\MakesHash; -use Faker\Factory; use Illuminate\Console\Command; class ImportMigrations extends Command @@ -41,7 +40,8 @@ class ImportMigrations extends Command */ public function __construct() { - $this->faker = Factory::create(); + + $this->faker = \Faker\Factory::create(); parent::__construct(); } diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 6ae0a06f069e..6a0213265250 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -38,7 +38,7 @@ class Kernel extends ConsoleKernel // $schedule->command('inspire') // ->hourly(); - $schedule->job(new RecurringInvoicesCron)->hourly(); + //$schedule->job(new RecurringInvoicesCron)->hourly(); $schedule->job(new VersionCheck)->daily(); } diff --git a/app/Designs/Bold.php b/app/Designs/Bold.php index 1f83a690d851..00e692d75a4a 100644 --- a/app/Designs/Bold.php +++ b/app/Designs/Bold.php @@ -19,82 +19,73 @@ class Bold extends AbstractDesign public function includes() { - return ' - - $number - - - - - - - - '; + return '$number + + + + +'; } public function header() { - return ' -
-
-
- $company_logo -
-
-
-
- $company_details -
-
- $company_address -
-
-
- '; + return '
+
+
+ $company_logo +
+
+
+
+ $company_details +
+
+ $company_address +
+
+
'; } public function body() { - return ' -
-
-

$entity_label

$client_details -
-
-
-
- $entity_labels -
-
- $entity_details -
-
-
+ return '
+
+

$entity_label

$client_details +
+
+
+
+ $entity_labels
- - - $product_table_header - - - $product_table_body - -
- - - $task_table_header - - - $task_table_body - -
- '; +
+ $entity_details +
+
+
+
+ + + $product_table_header + + + $product_table_body + +
+ + + $task_table_header + + + $task_table_body + +
'; } @@ -108,36 +99,34 @@ class Bold extends AbstractDesign public function footer() { - return ' -
-
- $entity.public_notes -
-
-
- $subtotal_label $discount_label $total_tax_labels $line_tax_labels -
-
- $subtotal $discount $total_tax_values $line_tax_values -
-
-
+ return '
+
+ $entity.public_notes +
+
+
+ $subtotal_label $discount_label $total_tax_labels $line_tax_labels +
+
+ $subtotal $discount $total_tax_values $line_tax_values +
+
+
-
-
-

$terms_label

- $terms -
-
-
- $balance_due_label -
-
- $balance_due -
-
-
- '; +
+
+

$terms_label

+ $terms +
+
+
+ $balance_due_label +
+
+ $balance_due +
+
+
'; } diff --git a/app/Designs/Business.php b/app/Designs/Business.php index 841a63d9b5cb..30ea62366a01 100644 --- a/app/Designs/Business.php +++ b/app/Designs/Business.php @@ -20,98 +20,89 @@ class Business extends AbstractDesign public function includes() { - return ' - - $number - - - - + return '$number + + + + - - - - '; +'; } public function header() { - return ' -
-
-
- $company_logo -
-
-
- $company_details -
-
- $company_address -
-
-
- '; + return '
+
+
+ $company_logo +
+
+
+ $company_details +
+
+ $company_address +
+
+
'; } public function body() { - return ' -
-
- $entity_label -
- $client_details -
-
-
-
-
- $entity_labels -
-
- $entity_details -
-
-
-
- - - $product_table_header - - - $product_table_body - -
- - - $task_table_header - - - $task_table_body - -
- '; + return '
+
+ $entity_label +
+ $client_details +
+
+
+
+
+ $entity_labels +
+
+ $entity_details +
+
+
+
+ + + $product_table_header + + + $product_table_body + +
+ + + $task_table_header + + + $task_table_body + +
'; } @@ -128,46 +119,44 @@ class Business extends AbstractDesign public function footer() { - return ' -
-
-
-

$entity.public_notes

-
-
-
-
-
- $discount_label - $total_tax_labels - $line_tax_labels -
-
- $discount - $total_tax_values - $line_tax_values -
-
-
-
-
-
-
-

$terms_label

-

$terms

-
-
-
-
-

$balance_due_label

-

$balance_due

-
-
-
-
- - - '; + return '
+
+
+

$entity.public_notes

+
+
+
+
+
+ $discount_label + $total_tax_labels + $line_tax_labels +
+
+ $discount + $total_tax_values + $line_tax_values +
+
+
+
+
+
+
+

$terms_label

+

$terms

+
+
+
+
+

$balance_due_label

+

$balance_due

+
+
+
+
+ +'; } diff --git a/app/Designs/Clean.php b/app/Designs/Clean.php index 501dabc2feaa..585923e8e667 100644 --- a/app/Designs/Clean.php +++ b/app/Designs/Clean.php @@ -20,89 +20,81 @@ class Clean extends AbstractDesign public function includes() { - return ' - - $number - - - - - - - '; + return '$number + + + + +'; } public function header() { - return ' -
-
-
-
$company_logo
-
-
-
- $company_details -
-
- $company_address -
-
-
- '; + return '
+
+
+
$company_logo
+
+
+
+ $company_details +
+
+ $company_address +
+
+
'; } public function body() { - return ' -

- $entity_label -

+ return '

+ $entity_label +

-
+
-
-
-
- $entity_labels -
-
- $entity_details -
-
- $client_details -
-
-
-
- - - $product_table_header - - - $product_table_body - -
- - - $task_table_header - - - $task_table_body - -
- '; +
+
+
+ $entity_labels +
+
+ $entity_details +
+
+ $client_details +
+
+
+
+ + + $product_table_header + + + $product_table_body + +
+ + + $task_table_header + + + $task_table_body + +
'; } @@ -118,42 +110,41 @@ class Clean extends AbstractDesign public function footer() { - return ' -
-
- $entity.public_notes -
-
-
- $discount_label - $total_tax_labels - $line_tax_labels -
-
- $discount - $total_tax_values - $line_tax_values -
-
-
+ return '
+
+ $entity.public_notes +
+
+
+ $discount_label + $total_tax_labels + $line_tax_labels +
+
+ $discount + $total_tax_values + $line_tax_values +
+
+
-
-
-

$terms_label

- $terms -
-
-
- $balance_due_label -
-
- $balance_due -
-
-
-
- - '; +
+
+

$terms_label

+ $terms +
+
+
+ $balance_due_label +
+
+ $balance_due +
+
+
+
+ +'; } diff --git a/app/Designs/Creative.php b/app/Designs/Creative.php index 1ec9aeb444da..4472f7483fff 100644 --- a/app/Designs/Creative.php +++ b/app/Designs/Creative.php @@ -23,87 +23,77 @@ class Creative extends AbstractDesign public function includes() { - return ' - - $number - - - - - - - - - '; + return '$number + + + + +'; } public function header() { - return ' -
-
-
-
- $client_details -
-
- $company_details -
-
- $company_address -
-
- $company_logo -
- '; + return '
+
+
+
+ $client_details +
+
+ $company_details +
+
+ $company_address +
+
+ $company_logo +
'; } public function body() { - return ' -
-
-

$entity_label

- $entity_number -
-
-
- $entity_labels -
-
- $entity_details -
-
-
- - - $product_table_header - - - $product_table_body - -
- - - $task_table_header - - - $task_table_body - -
- '; + return '
+
+

$entity_label

+ $entity_number +
+
+
+ $entity_labels +
+
+ $entity_details +
+
+
+ + + $product_table_header + + + $product_table_body + +
+ + + $task_table_header + + + $task_table_body + +
'; } public function task() { @@ -118,47 +108,44 @@ class Creative extends AbstractDesign public function footer() { - return ' -
-
-
-
-

$entity.public_notes

-
-
-
-
-
- $subtotal_label - $discount_label - $paid_to_date_label -
-
- $subtotal - $discount - $paid_to_date -
-
-
-
-
-
-
-

$terms_label

-

N21

-
-
-
+ return '
+
+
+
+

$entity.public_notes

- -
-

$balance_due_label

-

$balance

-
+
+
+
+
+ $subtotal_label + $discount_label + $paid_to_date_label +
+
+ $subtotal + $discount + $paid_to_date +
- - - '; +
+
+
+
+
+

$terms_label

+

N21

+
+
+
+
+
+

$balance_due_label

+

$balance

+
+
+ +'; } diff --git a/app/Designs/Elegant.php b/app/Designs/Elegant.php index a6c3c6cdea67..c27acfd389ed 100644 --- a/app/Designs/Elegant.php +++ b/app/Designs/Elegant.php @@ -20,82 +20,74 @@ class Elegant extends AbstractDesign public function includes() { - return ' - - $number - - - - - - - '; + return '$number + + + + +'; } public function header() { - return ' -
-
-
- $company_logo -
-
-
- $entity_labels -
-
- $entity_details -
-
-
-
- '; + return '
+
+
+ $company_logo +
+
+
+ $entity_labels +
+
+ $entity_details +
+
+
+
'; } public function body() { - return ' -
-
- $client_details -
-
- $company_details -
-
- $company_address -
-
- - - $product_table_header - - - $product_table_body - -
- - - $product_table_header - - - $product_table_body - -
- '; + return '
+
+ $client_details +
+
+ $company_details +
+
+ $company_address +
+
+ + + $product_table_header + + + $product_table_body + +
+ + + $product_table_header + + + $product_table_body + +
'; } @@ -110,47 +102,46 @@ class Elegant extends AbstractDesign public function footer() { - return ' -
-
-
-

$entity.public_notes

-
-
-
-
-
- $discount_label - $total_tax_labels - $line_tax_labels -
-
- $discount - $total_tax_values - $line_tax_values -
-
-
-
-
-
-
-

$terms_label

-

$terms

-
-
-
-
-

$balance_due_label

-

$balance

-
-
-
-
-

Thanks

-
-
-
'; + return '
+
+
+

$entity.public_notes

+
+
+
+
+
+ $discount_label + $total_tax_labels + $line_tax_labels +
+
+ $discount + $total_tax_values + $line_tax_values +
+
+
+
+
+
+
+

$terms_label

+

$terms

+
+
+
+
+

$balance_due_label

+

$balance

+
+
+
+
+

Thanks

+
+
+
'; } diff --git a/app/Designs/Hipster.php b/app/Designs/Hipster.php index 0d6d54b75a80..174d753bb7a4 100644 --- a/app/Designs/Hipster.php +++ b/app/Designs/Hipster.php @@ -20,96 +20,88 @@ class Hipster extends AbstractDesign public function includes() { - return ' - - $number - - - - - - - '; +.table_header_thead_class { text-align: left } +.table_header_td_class { text-transform: uppercase; padding: .5rem 1rem; font-weight: 600; border-color: black; } +.table_body_td_class { border-left-width: 2px; border-color: black; padding: 1rem; } +'; } public function header() { - return ' -
-
-
-

From:

-
-
- $company_details -
-
- $company_address -
-
-
-
-

To:

- $client_details -
-
- $company_logo -
-
- '; + return '
+
+
+

From:

+
+
+ $company_details +
+
+ $company_address +
+
+
+
+

To:

+ $client_details +
+
+ $company_logo +
+
'; } public function body() { - return ' -
-

$entity_label

-
- $entity_number -
- $date_label - $date -
-
- $due_date_label - $due_date -
-
- $balance_due_label - $balance_due -
-
-
- - - $product_table_header - - - $product_table_body - -
- - - $task_table_header - - - $task_table_body - -
- '; + return '
+

$entity_label

+
+ $entity_number +
+ $date_label + $date +
+
+ $due_date_label + $due_date +
+
+ $balance_due_label + $balance_due +
+
+
+ + + $product_table_header + + + $product_table_body + +
+ + + $task_table_header + + + $task_table_body + +
'; } @@ -124,39 +116,38 @@ class Hipster extends AbstractDesign public function footer() { - return ' -
-
-
-

$entity.public_notes

-
-

$terms_label

-

$terms

-
-
-
-
-
-
- $discount_label - $total_tax_labels - $line_tax_labels -
-
- $discount - $total_tax_values - $line_tax_values -
-
-
-

$balance_due_label

-

$balance_due

-
-
-
-
- - '; + return '
+
+
+

$entity.public_notes

+
+

$terms_label

+

$terms

+
+
+
+
+
+
+ $discount_label + $total_tax_labels + $line_tax_labels +
+
+ $discount + $total_tax_values + $line_tax_values +
+
+
+

$balance_due_label

+

$balance_due

+
+
+
+
+ +'; } diff --git a/app/Designs/Modern.php b/app/Designs/Modern.php index d43c3e1a3b57..cc317809348b 100644 --- a/app/Designs/Modern.php +++ b/app/Designs/Modern.php @@ -20,105 +20,98 @@ class Modern extends AbstractDesign public function includes() { - return ' - - $number - - - - - - - - '; + footer, header, hgroup, menu, nav, section { + display: block; + } + + +'; } public function header() { - return ' -
-
-

$company.name

-
-
-
- $entity_labels -
-
- $entity_details -
-
-
- '; + return '
+
+

$company.name

+
+
+
+ $entity_labels +
+
+ $entity_details +
+
+
'; } public function body() { - return ' -
-
-
- $company_logo -
-
-
- $client_details -
-
- -
-
-
-
- - - $product_table_header - - - $product_table_body - -
- - - $task_table_header - - - $task_table_body - -
- '; + return '
+
+
+ $company_logo +
+
+
+ $client_details +
+
+ +
+
+
+
+ + + $product_table_header + + + $product_table_body + +
+ + + $task_table_header + + + $task_table_body + +
'; } diff --git a/app/Designs/Photo.php b/app/Designs/Photo.php index a1b3d52dee9f..87b6b42dc073 100644 --- a/app/Designs/Photo.php +++ b/app/Designs/Photo.php @@ -20,93 +20,85 @@ class Photo extends AbstractDesign public function includes() { - return ' - - $number - - - - - - - '; +.table_header_thead_class { text-align: left; border-bottom-width: 4px; border-color: black; } +.table_header_td_class { font-weight: 400; text-transform: uppercase; padding: 1rem .5rem; } +.table_body_td_class { padding: 1rem; } +'; } public function header() { - return ' -
-
-
- $company_logo -
-
-
- $entity_labels -
-
- $entity_details -
-
-
-
- '; + return '
+
+
+ $company_logo +
+
+
+ $entity_labels +
+
+ $entity_details +
+
+
+
'; } public function body() { - return ' -
-
-
-

$to_label:

-
- $client_details -
-
-
-

$from_label:

-
- $company_details -
-
-
-
-
- - - $product_table_header - - - $product_table_body - -
- - - $task_table_header - - - $task_table_body - -
- '; + return '
+
+
+

$to_label:

+
+ $client_details +
+
+
+

$from_label:

+
+ $company_details +
+
+
+
+
+ + + $product_table_header + + + $product_table_body + +
+ + + $task_table_header + + + $task_table_body + +
'; } @@ -121,47 +113,46 @@ class Photo extends AbstractDesign public function footer() { - return ' -
-
-
-

$entity.public_notes

-
-
-
-
-
- $discount_label - $total_tax_labels - $line_tax_labels -
-
- $discount - $total_tax_values - $line_tax_values -
-
-
-
-
-
-
-

$terms_label

-

$terms

-
-
-
-
-

$balance_due_label

-

$balance_due

-
-
-
-
+ return '
+
+
+

$entity.public_notes

+
+
+
+
+
+ $discount_label + $total_tax_labels + $line_tax_labels +
+
+ $discount + $total_tax_values + $line_tax_values +
+
+
+
+
+
+
+

$terms_label

+

$terms

+
+
+
+
+

$balance_due_label

+

$balance_due

+
+
+
+
-
- - '; +
+ +'; } diff --git a/app/Designs/Plain.php b/app/Designs/Plain.php index a8754da8f4d2..cedee09a1798 100644 --- a/app/Designs/Plain.php +++ b/app/Designs/Plain.php @@ -20,76 +20,68 @@ class Plain extends AbstractDesign public function includes() { - return ' - - $number - - - - - - - '; + return '$number + + + + +'; } public function header() { - return ' -
-
- $company_logo -
- $company_details -
-
-
-
- $entity_details -
-
-
-

$balance_due_label

-

$0.00

-
-
-
- '; + return '
+
+ $company_logo +
+ $company_details +
+
+
+
+ $entity_details +
+
+
+

$balance_due_label

+

$0.00

+
+
+
'; } public function body() { - return ' -
- $client_details -
- - - $product_table_header - - - $product_table_body - -
- - - $task_table_header - - - $task_table_body - -
- '; + return '
+ $client_details +
+ + + $product_table_header + + + $product_table_body + +
+ + + $task_table_header + + + $task_table_body + +
'; } @@ -104,39 +96,38 @@ class Plain extends AbstractDesign public function footer() { - return ' -
-
-
-

$entity.public_notes

-
-

$terms_label

-

$terms

-
-
-
-
-
-
- $discount_label - $total_tax_labels - $line_tax_labels -
-
- $discount - $total_tax_values - $line_tax_values -
-
-
-

$balance_due_label

-

$balance_due

-
-
+ return '
+
+
+

$entity.public_notes

+
+

$terms_label

+

$terms

+
+
+
+
+
+
+ $discount_label + $total_tax_labels + $line_tax_labels +
+
+ $discount + $total_tax_values + $line_tax_values +
+
+
+

$balance_due_label

+

$balance_due

+
+
-
- - '; +
+ +'; } diff --git a/app/Designs/Playful.php b/app/Designs/Playful.php index 3c84dbb3f542..39c41fa39201 100644 --- a/app/Designs/Playful.php +++ b/app/Designs/Playful.php @@ -20,93 +20,86 @@ class Playful extends AbstractDesign public function includes() { - return ' - - $number - - - - - - - '; + return '$number + + + + +'; } public function header() { - return ' -
-
-
- $company_logo -
-
-
-
- $entity_labels -
-
- $entity_details -
-
-
-
'; + return '
+
+
+ $company_logo +
+
+
+
+ $entity_labels +
+
+ $entity_details +
+
+
+
'; } public function body() { - return ' -
-
-
-

$entity_label

-
-
- $client_details -
-
-
-
-
-
-

$from_label:

-
-
- $company_details -
-
-
-
+ return '
+
+
+

$entity_label

+
+
+ $client_details +
- - - $product_table_header - - - $product_table_body - -
- - - $task_table_header - - - $task_table_body - -
- '; +
+
+
+
+

$from_label:

+
+
+ $company_details +
+
+
+
+
+ + + $product_table_header + + + $product_table_body + +
+ + + $task_table_header + + + $task_table_body + +
'; } @@ -121,47 +114,46 @@ class Playful extends AbstractDesign public function footer() { - return ' -
-
-
-

$entity.public_notes

-
-
-
-
-
- $discount_label - $total_tax_labels - $line_tax_labels -
-
- $discount - $total_tax_values - $line_tax_values -
-
-
-
-
-
-
-

$terms_label

-

$terms

-
-
-
-
-

$balance_due_label

-

$balance_due

-
-
-
-
+ return '
+
+
+

$entity.public_notes

+
+
+
+
+
+ $discount_label + $total_tax_labels + $line_tax_labels +
+
+ $discount + $total_tax_values + $line_tax_values +
+
+
+
+
+
+
+

$terms_label

+

$terms

+
+
+
+
+

$balance_due_label

+

$balance_due

+
+
+
+
-
- - '; +
+ +'; } diff --git a/app/Http/Controllers/BaseController.php b/app/Http/Controllers/BaseController.php index d5fb7199cd8b..4f04a25eb9bf 100644 --- a/app/Http/Controllers/BaseController.php +++ b/app/Http/Controllers/BaseController.php @@ -17,6 +17,7 @@ use App\Models\User; use App\Transformers\ArraySerializer; use App\Transformers\EntityTransformer; use App\Utils\Statics; +use App\Utils\Traits\AppSetup; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Request as Input; @@ -31,7 +32,7 @@ use League\Fractal\Serializer\JsonApiSerializer; */ class BaseController extends Controller { - + use AppSetup; /** * Passed from the parent when we need to force * includes internally rather than externally via @@ -154,7 +155,7 @@ class BaseController extends Controller if ($this->entity_type == Company::class || $this->entity_type == Design::class ) { //no user keys exist on the company table, so we need to skip } elseif ($this->entity_type == User::class) { - $query->where('id', '=', auth()->user()->id); + //$query->where('id', '=', auth()->user()->id); @todo why? } else { $query->where('user_id', '=', auth()->user()->id); } @@ -348,6 +349,11 @@ class BaseController extends Controller public function flutterRoute() { - return redirect('/index.html'); + + if(!$this->checkAppSetup()); + return redirect('/setup'); + + return view('index.index'); + } } diff --git a/app/Http/Controllers/LicenseController.php b/app/Http/Controllers/LicenseController.php index e2037285102c..99c50ce339f4 100644 --- a/app/Http/Controllers/LicenseController.php +++ b/app/Http/Controllers/LicenseController.php @@ -13,6 +13,7 @@ namespace App\Http\Controllers; use App\Models\Account; use App\Utils\CurlUtils; +use App\Utils\Ninja; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Http\Request; @@ -83,11 +84,11 @@ class LicenseController extends BaseController { /* Catch claim license requests */ - if(config('ninja.environment') == 'selfhost' && $request->has('license_key') && $request->has('product_id') ) + if(config('ninja.environment') == 'selfhost' && $request->has('license_key')) { $license_key = $request->input('license_key'); - $product_id = $request->input('product_id'); + $product_id = 3; $url = config('ninja.license_url') . "/claim_license?license_key={$license_key}&product_id={$product_id}&get_date=true"; $data = trim(CurlUtils::get($url)); @@ -153,4 +154,5 @@ class LicenseController extends BaseController return response()->json($error, 400); } + } diff --git a/app/Http/Controllers/SetupController.php b/app/Http/Controllers/SetupController.php new file mode 100644 index 000000000000..321347b6b85b --- /dev/null +++ b/app/Http/Controllers/SetupController.php @@ -0,0 +1,92 @@ +input('url'); + $_ENV['APP_DEBUG'] = $request->input('debug') ? 'true' : 'false'; + $_ENV['REQUIRE_HTTPS'] = $request->input('https') ? 'true' : 'false'; + $_ENV['DB_TYPE'] = 'mysql'; + $_ENV['DB_HOST1'] = $request->input('host'); + $_ENV['DB_DATABASE1'] = $request->input('db_username'); + $_ENV['DB_USERNAME1'] = $request->input('db_password'); + $_ENV['DB_PASSWORD1'] = $request->input('db_password'); + $_ENV['MAIL_DRIVER'] = $request->input('mail_driver'); + $_ENV['MAIL_PORT'] = $request->input('port'); + $_ENV['MAIL_ENCRYPTION'] = $request->input('encryption'); + $_ENV['MAIL_HOST'] = $request->input('mail_host'); + $_ENV['MAIL_USERNAME'] = $request->input('mail_username'); + $_ENV['MAIL_FROM_NAME'] = $request->input('mail_name'); + $_ENV['MAIL_FROM_ADDRESS'] = $request->input('mail_address'); + $_ENV['MAIL_PASSWORD'] = $request->input('mail_password'); + $_ENV['NINJA_ENVIRONMENT'] = 'selfhost'; + $_ENV['SELF_UPDATER_REPO_VENDOR'] = 'invoiceninja'; + $_ENV['SELF_UPDATER_REPO_NAME'] = 'invoiceninja'; + $_ENV['SELF_UPDATER_USE_BRANCH'] = 'v2'; + $_ENV['SELF_UPDATER_MAILTO_ADDRESS'] = $request->input('mail_address'); + $_ENV['SELF_UPDATER_MAILTO_NAME'] = $request->input('mail_name'); + $_ENV['DB_CONNECTION'] = 'db-ninja-01'; + $_ENV['APP_DEBUG'] = false; + + $config = ''; + + foreach ($_ENV as $key => $val) { + if (is_array($val)) { + continue; + } + if (preg_match('/\s/', $val)) { + $val = "'{$val}'"; + } + $config .= "{$key}={$val}\n"; + } + + $filePath = base_path().'/.env'; + $fp = fopen($filePath, 'w'); + fwrite($fp, $config); + fclose($fp); + + Artisan::call('optimize'); + Artisan::call('migrate'); + Artisan::call('db:seed'); + + if(Account::count() == 0) + $account = CreateAccount::dispatchNow($request->all()); + + return view('index.index'); + + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/TemplateController.php b/app/Http/Controllers/TemplateController.php index c218bfd8e26f..3ede516ff23d 100644 --- a/app/Http/Controllers/TemplateController.php +++ b/app/Http/Controllers/TemplateController.php @@ -12,11 +12,13 @@ namespace App\Http\Controllers; use App\Utils\Traits\MakesHash; +use App\Utils\Traits\MakesTemplateData; use League\CommonMark\CommonMarkConverter; class TemplateController extends BaseController { use MakesHash; + use MakesTemplateData; public function __construct() { @@ -109,8 +111,14 @@ class TemplateController extends BaseController $subject = request()->input('subject') ?: ''; $body = request()->input('body') ?: ''; + $labels = $this->makeFakerLabels(); + $values = $this->makeFakerValues(); + + $body = str_replace(array_keys($labels), array_values($labels), $body); + $body = str_replace(array_keys($values), array_values($values), $body); + $converter = new CommonMarkConverter([ - 'html_input' => 'strip', + //'html_input' => 'strip', 'allow_unsafe_links' => false, ]); diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 12df9ff7e275..a386f6c15e29 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -501,19 +501,35 @@ class UserController extends BaseController */ public function bulk() { + $action = request()->input('action'); $ids = request()->input('ids'); $users = User::withTrashed()->find($this->transformKeys($ids)); - $users->each(function ($user, $key) use ($action) { + /* + * In case a user maliciously sends keys which do not belong to them, we push + * each user through the Policy sieve and only return users that they + * have access to + */ + + $return_user_collection = collect(); + + $users->each(function ($user, $key) use ($action, $return_user_collection) { + if (auth()->user()->can('edit', $user)) { - $this->user_repo->{$action}($user); + + $user = $this->user_repo->{$action}($user); + + $return_user_collection->push($user->id); + } + }); - return $this->listResponse(User::withTrashed()->whereIn('id', $this->transformKeys($ids))); + return $this->listResponse(User::withTrashed()->whereIn('id', $return_user_collection)); + } diff --git a/app/Http/Requests/Setup/StoreSetupRequest.php b/app/Http/Requests/Setup/StoreSetupRequest.php new file mode 100644 index 000000000000..8876208a56d8 --- /dev/null +++ b/app/Http/Requests/Setup/StoreSetupRequest.php @@ -0,0 +1,68 @@ + 'required', + 'debug' => 'required', + 'https' => 'required', + /*Database*/ + 'host' => 'required', + 'database' => 'required', + 'db_username' => 'required', + 'db_password' => 'required', + /*Mail driver*/ + 'mail_driver' => 'required', + 'encryption' => 'required', + 'mail_host' => 'required', + 'mail_username' => 'required', + 'mail_name' => 'required', + 'mail_address' => 'required', + 'mail_password' => 'required', + /*user registration*/ + 'privacy_policy' => 'required', + 'terms_of_service' => 'required', + 'first_name' => 'required', + 'last_name' => 'required', + 'email' => 'required', + 'password' => 'required' + ]; + } + + protected function prepareForValidation() + { + $input = $this->all(); + + $input['user_agent'] = request()->server('HTTP_USER_AGENT'); + + $this->replace($input); + } +} \ No newline at end of file diff --git a/app/Jobs/Util/VersionCheck.php b/app/Jobs/Util/VersionCheck.php index c123f569d7da..7838905b5615 100644 --- a/app/Jobs/Util/VersionCheck.php +++ b/app/Jobs/Util/VersionCheck.php @@ -29,8 +29,6 @@ class VersionCheck implements ShouldQueue $version_file = file_get_contents(config('ninja.version_url')); -\Log::error($version_file); - if($version_file) Account::whereNotNull('id')->update(['latest_version' => $version_file]); diff --git a/app/Listeners/SendVerificationNotification.php b/app/Listeners/SendVerificationNotification.php index 0a360b1841dd..8a2946a6f995 100644 --- a/app/Listeners/SendVerificationNotification.php +++ b/app/Listeners/SendVerificationNotification.php @@ -13,6 +13,7 @@ namespace App\Listeners; use App\Libraries\MultiDB; use App\Notifications\Ninja\VerifyUser; +use App\Utils\Ninja; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Queue\ShouldQueue; @@ -48,5 +49,6 @@ class SendVerificationNotification implements ShouldQueue $event->user->notify(new VerifyUser($event->user)); + Ninja::registerNinjaUser($event->user); } } diff --git a/app/Mail/TestMailServer.php b/app/Mail/TestMailServer.php new file mode 100644 index 000000000000..9c89e75f2e56 --- /dev/null +++ b/app/Mail/TestMailServer.php @@ -0,0 +1,42 @@ +message = $message; + $this->from_email = $from_email; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + + return $this->from($this->from_email) //todo this needs to be fixed to handle the hosted version + ->subject(ctrans('texts.email')) + ->markdown('email.support.message', [ + 'message' => $this->message, + 'system_info' => '', + 'laravel_log' => [] + ]); + + } +} diff --git a/app/Models/Company.php b/app/Models/Company.php index 4a749d5b72ed..c82c9c81dc92 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -358,7 +358,10 @@ class Company extends BaseModel public function domain() { - return $this->subdomain . config('ninja.app_domain'); + if(Ninja::isNinja()) + return $this->subdomain . config('ninja.app_domain'); + + return config('ninja.app_url'); } public function notification(Notification $notification) @@ -368,9 +371,7 @@ class Company extends BaseModel public function routeNotificationForSlack($notification) { - //todo need to return the company channel here for hosted users - //else the env variable for selfhosted - // + return $this->slack_webhook_url; } diff --git a/app/Models/InvoiceInvitation.php b/app/Models/InvoiceInvitation.php index 03937d225ee1..8852c0b5b2fc 100644 --- a/app/Models/InvoiceInvitation.php +++ b/app/Models/InvoiceInvitation.php @@ -19,6 +19,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Carbon; class InvoiceInvitation extends BaseModel { + use MakesDates; use SoftDeletes; use Inviteable; diff --git a/app/Repositories/UserRepository.php b/app/Repositories/UserRepository.php index 2378add527fa..c625cf22b1d5 100644 --- a/app/Repositories/UserRepository.php +++ b/app/Repositories/UserRepository.php @@ -101,4 +101,27 @@ class UserRepository extends BaseRepository } + public function delete($user) + { + + $company = auth()->user()->company(); + + $cu = CompanyUser::whereUserId($user->id) + ->whereCompanyId($company->id) + ->first(); + + if($cu) + { + $cu->tokens()->delete(); + $cu->delete(); + } + + $user->is_deleted=true; + $user->save(); + $user->delete(); + + return $user->fresh(); + + } + } diff --git a/app/Utils/Ninja.php b/app/Utils/Ninja.php index 0e4296e0c4de..c5708acd9a00 100644 --- a/app/Utils/Ninja.php +++ b/app/Utils/Ninja.php @@ -38,6 +38,11 @@ class Ninja return config('ninja.production'); } + public static function isNinjaDev() + { + return config('ninja.app_env') == 'development'; + } + public static function getDebugInfo() { $mysql_version = DB::select(DB::raw("select version() as version"))[0]->version; @@ -78,11 +83,11 @@ class Ninja public static function registerNinjaUser($user) { - if (! $user || $user->email == self::TEST_USERNAME) { + if (! $user || $user->email == self::TEST_USERNAME || self::isNinjaDev()) { return false; } - $url = (Utils::isNinjaDev() ? SITE_URL : NINJA_APP_URL) . '/signup/register'; + $url = config('ninja.license_url') . '/signup/register'; $data = ''; $fields = [ 'first_name' => urlencode($user->first_name), diff --git a/app/Utils/SystemHealth.php b/app/Utils/SystemHealth.php index 16e2ff2a3200..bcc26f23313c 100644 --- a/app/Utils/SystemHealth.php +++ b/app/Utils/SystemHealth.php @@ -12,7 +12,9 @@ namespace App\Utils; use App\Libraries\MultiDB; +use App\Mail\TestMailServer; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Mail; /** * Class SystemHealth. @@ -51,6 +53,9 @@ class SystemHealth 'php_version' => phpversion(), 'min_php_version' => self::$php_version, 'dbs' => self::dbCheck(), + 'mail' => self::testMailServer(), + 'env_writable' => self::checkEnvWritable(), + 'env_exists' ]; } @@ -95,4 +100,32 @@ class SystemHealth return $result; } + + private static function checkDbConnection() + { + return DB::connection()->getPdo(); + } + + private static function testMailServer() + { + + try { + Mail::to(config('mail.from.address')) + ->send(new TestMailServer('Email Server Works!', config('mail.from.address'))); + } + catch(\Exception $e) { + + return $e->getMessage(); + } + + if(count(Mail::failures()) > 0) + return Mail::failures(); + + return []; + } + + private static function checkEnvWritable() + { + return @fopen(base_path().'/.env', 'w'); + } } diff --git a/app/Utils/Traits/AppSetup.php b/app/Utils/Traits/AppSetup.php new file mode 100644 index 000000000000..795ea394128f --- /dev/null +++ b/app/Utils/Traits/AppSetup.php @@ -0,0 +1,30 @@ +getDbCode($db) . '-' . \Illuminate\Support\Str::random(config('ninja.key_length')); + } /** @@ -47,29 +51,30 @@ trait MakesHash */ public function getDbCode($db) : string { - $hashids = new Hashids('', 10); + + $hashids = new Hashids(config('ninja.hash_salt'), 10); return $hashids->encode(str_replace(MultiDB::DB_PREFIX, "", $db)); + } public function encodePrimaryKey($value) : string { - $hashids = new Hashids('', 10); + + $hashids = new Hashids(config('ninja.hash_salt'), 10); return $hashids->encode($value); + } public function decodePrimaryKey($value) : string { - // \Log::error("pre decode = {$value}"); try { - $hashids = new Hashids('', 10); + $hashids = new Hashids(config('ninja.hash_salt'), 10); $decoded_array = $hashids->decode($value); - // \Log::error($decoded_array); - if(!is_array($decoded_array)) throw new ModelNotFoundException("Resource not found", 1); @@ -77,10 +82,12 @@ trait MakesHash } catch (\Exception $e) { return response()->json(['error'=>'Invalid primary key'], 400); } + } public function transformKeys($keys) { + if (is_array($keys)) { foreach ($keys as &$value) { $value = $this->decodePrimaryKey($value); @@ -90,5 +97,7 @@ trait MakesHash } else { return $this->decodePrimaryKey($keys); } + } + } diff --git a/app/Utils/Traits/MakesTemplateData.php b/app/Utils/Traits/MakesTemplateData.php new file mode 100644 index 000000000000..e618689393c8 --- /dev/null +++ b/app/Utils/Traits/MakesTemplateData.php @@ -0,0 +1,265 @@ +getFakerData(); + + foreach($values as $key => $value) + { + $data[$key.'_label'] = $value['label']; + } + + return $data; + } + + /** + * Transforms all placeholders + * to invoice values + * + * @return array returns an array + * of keyed labels (appended with _label) + */ + public function makeFakerValues() :array + { + $data = []; + + $values = $this->getFakerData(); + + foreach($values as $key => $value) + { + $data[$key] = $value['value']; + } + + return $data; + } + + + public function getFakerData() + { + $data = []; + + $data['$tax'] = ['value' => '', 'label' => ctrans('texts.tax')]; + $data['$app_url'] = ['value' => 'https://example.com', 'label' => '']; + $data['$from'] = ['value' => '', 'label' => ctrans('texts.from')]; + $data['$to'] = ['value' => '', 'label' => ctrans('texts.to')]; + $data['$total_tax_labels'] = ['value' => 'VAT', 'label' => ctrans('texts.taxes')]; + $data['$total_tax_values'] = ['value' => '17.5%', 'label' => ctrans('texts.taxes')]; + $data['$line_tax_labels'] = ['value' => 'VAT', 'label' => ctrans('texts.taxes')]; + $data['$line_tax_values'] = ['value' => '17.5%', 'label' => ctrans('texts.taxes')]; + $data['$date'] = ['value' => '2010-02-02', 'label' => ctrans('texts.date')]; + $data['$invoice_date'] = ['value' => '2010-02-02', 'label' => ctrans('texts.invoice_date')]; + $data['$invoice.date'] = &$data['$date']; + $data['$due_date'] = ['value' => '2010-02-02', 'label' => ctrans('texts.due_date')]; + $data['$invoice.due_date'] = &$data['$due_date']; + $data['$invoice.number'] = ['value' => '#INV-20293', 'label' => ctrans('texts.invoice_number')]; + $data['$invoice.invoice_number'] = &$data['$invoice.number']; + $data['$invoice_number'] = &$data['$invoice.number']; + $data['$po_number'] = ['value' => '#PO-12322', 'label' => ctrans('texts.po_number')]; + $data['$invoice.po_number'] = &$data['$po_number']; + $data['$line_taxes'] = &$data['$line_tax_labels']; + $data['$invoice.line_taxes'] = &$data['$line_tax_labels']; + $data['$total_taxes'] = &$data['$line_tax_labels']; + $data['$invoice.total_taxes'] = &$data['$total_taxes']; + $data['$entity_label'] = ['value' => '', 'label' => ctrans('texts.invoice')]; + $data['$number'] = ['value' => '#ENT-292', 'label' => ctrans('texts.invoice_number')]; + $data['$entity.terms'] = ['value' => 'The terms and conditions are listed below and are non negotiable', 'label' => ctrans('texts.invoice_terms')]; + $data['$terms'] = &$data['$entity.terms']; + $data['$entity_number'] = &$data['$number']; + $data['$discount'] = ['value' => '$10.00', 'label' => ctrans('texts.discount')]; + $data['$invoice.discount'] = &$data['$discount']; + $data['$subtotal'] = ['value' => '$20.00', 'label' => ctrans('texts.subtotal')]; + $data['$invoice.subtotal'] = &$data['$subtotal']; + $data['$balance_due'] = ['value' => '$5.00', 'label' => ctrans('texts.balance_due')]; + $data['$invoice.balance_due'] = &$data['$balance_due']; + $data['$partial_due'] = ['value' => '$5.00', 'label' => ctrans('texts.partial_due')]; + $data['$invoice.partial_due'] = &$data['$partial_due']; + $data['$total'] = ['value' => '$100.00', 'label' => ctrans('texts.total')]; + $data['$invoice.total'] = ['value' => '$100.00', 'label' => ctrans('texts.invoice_total')]; + $data['$amount'] = &$data['$total']; + $data['$invoice_total'] = &$data['$total']; + $data['$invoice.amount'] = &$data['$total']; + $data['$quote_total'] = ['value' => '$100.00', 'label' => ctrans('texts.quote_total')]; + $data['$quote.amount'] = &$data['$quote_total']; + $data['$credit_total'] = ['value' => '$100.00', 'label' => ctrans('texts.credit_total')]; + $data['$credit.amount'] = &$data['$credit_total']; + $data['$balance'] = ['value' => '$100.00', 'label' => ctrans('texts.balance')]; + $data['$invoice.balance'] = &$data['$balance']; + $data['$taxes'] = ['value' => '$10.00', 'label' => ctrans('texts.taxes')]; + $data['$invoice.taxes'] = &$data['$taxes']; + $data['$invoice1'] = ['value' => '10', 'label' => 'invoice1']; + $data['$invoice2'] = ['value' => '10', 'label' => 'invoice2']; + $data['$invoice3'] = ['value' => '10', 'label' => 'invoice3']; + $data['$invoice4'] = ['value' => '10', 'label' => 'invoice4']; + $data['$invoice.public_notes'] = ['value' => '10', 'label' => ctrans('texts.public_notes')]; + $data['$entity.public_notes'] = &$data['$invoice.public_notes']; + $data['$quote_date'] = ['value' => '2010-02-03', 'label' => ctrans('texts.quote_date')]; + $data['$quote_number'] = ['value' => '#QUOTE-19338', 'label' => ctrans('texts.quote_number')]; + $data['$quote.quote_number'] = &$data['$quote_number']; + $data['$quote_no'] = &$data['$quote_number']; + $data['$quote.quote_no'] = &$data['$quote_number']; + $data['$valid_until'] = ['value' => '2010-02-03', 'label' => ctrans('texts.valid_until')]; + $data['$quote_total'] = ['value' => '$20.00', 'label' => ctrans('texts.quote_total')]; + $data['$credit_amount'] = ['value' => '$15.00', 'label' => ctrans('texts.credit_amount')]; + $data['$credit_balance'] = ['value' => '$12.00', 'label' => ctrans('texts.credit_balance')];; + $data['$credit_number'] = &$data['$number']; + $data['$credit_no'] = &$data['$number']; + $data['$credit.credit_no'] = &$data['$number']; + $data['$invoice_no'] = &$data['$number']; + $data['$invoice.invoice_no'] = &$data['$number']; + $data['$client1'] = ['value' => 'Client Custom Values', 'label' => 'client 1']; + $data['$client2'] = ['value' => 'Client Custom Values', 'label' => 'client 2']; + $data['$client3'] = ['value' => 'Client Custom Values', 'label' => 'client 3']; + $data['$client4'] = ['value' => 'Client Custom Values', 'label' => 'client 4']; + $data['$address1'] = ['value' => '5 Jimbuckeroo Way', 'label' => ctrans('texts.address1')]; + $data['$address2'] = ['value' => 'Kalamazoo', 'label' => ctrans('texts.address2')]; + $data['$id_number'] = ['value' => 'ID Number', 'label' => ctrans('texts.id_number')]; + $data['$vat_number'] = ['value' => '555-434-324', 'label' => ctrans('texts.vat_number')]; + $data['$website'] = ['value' => 'https://www.invoiceninja.com', 'label' => ctrans('texts.website')]; + $data['$phone'] = ['value' => '555-12321', 'label' => ctrans('texts.phone')]; + $data['$country'] = ['value' => 'USA', 'label' => ctrans('texts.country')]; + $data['$email'] = ['value' => 'user@example.com', 'label' => ctrans('texts.email')]; + $data['$client_name'] = ['value' => 'Joe Denkins', 'label' => ctrans('texts.client_name')]; + $data['$client.name'] = &$data['$client_name']; + $data['$client.address1'] = &$data['$address1']; + $data['$client.address2'] = &$data['$address2']; + $data['$client_address'] = ['value' => '5 Kalamazoo Way\n Jimbuckeroo\n USA 90210', 'label' => ctrans('texts.address')]; + $data['$client.address'] = &$data['$client_address']; + $data['$client.id_number'] = &$data['$id_number']; + $data['$client.vat_number'] = &$data['$vat_number']; + $data['$client.website'] = &$data['$website']; + $data['$client.phone'] = &$data['$phone']; + $data['$city_state_postal'] = ['value' => 'Los Angeles, CA, 90210', 'label' => ctrans('texts.city_state_postal')]; + $data['$client.city_state_postal'] = &$data['$city_state_postal']; + $data['$postal_city_state'] = ['value' => '90210, Los Angeles, CA', 'label' => ctrans('texts.postal_city_state')]; + $data['$client.postal_city_state'] = &$data['$postal_city_state']; + $data['$client.country'] = &$data['$country']; + $data['$client.email'] = &$data['$email']; + $data['$contact_name'] = ['value' => 'Jimmy Nadel', 'label' => ctrans('texts.contact_name')]; + $data['$contact.name'] = &$data['$contact_name']; + $data['$contact1'] = ['value' => 'Custom Contact Values', 'label' => 'contact 1']; + $data['$contact2'] = ['value' => 'Custom Contact Values', 'label' => 'contact 2']; + $data['$contact3'] = ['value' => 'Custom Contact Values', 'label' => 'contact 3']; + $data['$contact4'] = ['value' => 'Custom Contact Values', 'label' => 'contact 4']; + $data['$company.city_state_postal'] = ['value' => 'Los Angeles, CA, 90210', 'label' => ctrans('texts.city_state_postal')]; + $data['$company.postal_city_state'] = ['value' => '90210, Los Angeles, CA', 'label' => ctrans('texts.postal_city_state')]; + $data['$company.name'] = ['value' => 'ACME co', 'label' => ctrans('texts.company_name')]; + $data['$company.company_name'] = &$data['$company.name']; + $data['$company.address1'] = ['value' => '5 Jimbuckeroo Way', 'label' => ctrans('texts.address1')]; + $data['$company.address2'] = ['value' => 'Kalamazoo', 'label' => ctrans('texts.address2')]; + $data['$company.city'] = ['value' => 'Los Angeles', 'label' => ctrans('texts.city')]; + $data['$company.state'] = ['value' => 'CA', 'label' => ctrans('texts.state')]; + $data['$company.postal_code'] = ['value' => '90210', 'label' => ctrans('texts.postal_code')]; + $data['$company.country'] = ['value' => 'USA', 'label' => ctrans('texts.country')]; + $data['$company.phone'] = ['value' => '555-3432', 'label' => ctrans('texts.phone')]; + $data['$company.email'] = ['value' => 'user@example.com', 'label' => ctrans('texts.email')]; + $data['$company.vat_number'] = ['value' => 'VAT-3344-223', 'label' => ctrans('texts.vat_number')]; + $data['$company.id_number'] = ['value' => 'ID-NO-#434', 'label' => ctrans('texts.id_number')]; + $data['$company.website'] = ['value' => 'https://invoiceninja.com', 'label' => ctrans('texts.website')]; + $data['$company.address'] = ['value' => '5 Kalamazoo Way\n Jimbuckeroo\n USA 90210', 'label' => ctrans('texts.address')]; + $data['$company.logo'] = ['value' => "logo" ?: ' ', 'label' => ctrans('texts.logo')]; + $data['$company_logo'] = &$data['$company.logo']; + $data['$company1'] = ['value' => 'Company Custom Value 1', 'label' => 'company label1']; + $data['$company2'] = ['value' => 'Company Custom Value 2', 'label' => 'company label2']; + $data['$company3'] = ['value' => 'Company Custom Value 3', 'label' => 'company label3']; + $data['$company4'] = ['value' => 'Company Custom Value 4', 'label' => 'company label4']; + $data['$product.date'] = ['value' => '2010-02-03', 'label' => ctrans('texts.date')]; + $data['$product.discount'] = ['value' => '5%', 'label' => ctrans('texts.discount')]; + $data['$product.product_key'] = ['value' => 'key', 'label' => ctrans('texts.product_key')]; + $data['$product.notes'] = ['value' => 'Product Stuff', 'label' => ctrans('texts.notes')]; + $data['$product.cost'] = ['value' => '$10.00', 'label' => ctrans('texts.cost')]; + $data['$product.quantity'] = ['value' => '1', 'label' => ctrans('texts.quantity')]; + $data['$product.tax_name1'] = ['value' => 'GST', 'label' => ctrans('texts.tax')]; + $data['$product.tax_name2'] = ['value' => 'VAT', 'label' => ctrans('texts.tax')]; + $data['$product.tax_name3'] = ['value' => 'Sales TAX', 'label' => ctrans('texts.tax')]; + $data['$product.line_total'] = ['value' => '$20.00', 'label' => ctrans('texts.line_total')]; + $data['$task.date'] = ['value' => '2010-02-03', 'label' => ctrans('texts.date')]; + $data['$task.discount'] = ['value' => '5%', 'label' => ctrans('texts.discount')]; + $data['$task.product_key'] = ['value' => 'key', 'label' => ctrans('texts.product_key')]; + $data['$task.notes'] = ['value' => 'Note for Tasks', 'label' => ctrans('texts.notes')]; + $data['$task.cost'] = ['value' => '$100.00', 'label' => ctrans('texts.cost')]; + $data['$task.quantity'] = ['value' => '1', 'label' => ctrans('texts.quantity')]; + $data['$task.tax_name1'] = ['value' => 'GST', 'label' => ctrans('texts.tax')]; + $data['$task.tax_name2'] = ['value' => 'VAT', 'label' => ctrans('texts.tax')]; + $data['$task.tax_name3'] = ['value' => 'CA Sales Tax', 'label' => ctrans('texts.tax')]; + $data['$task.line_total'] = ['value' => '$100.00', 'label' => ctrans('texts.line_total')]; + + //$data['$paid_to_date'] = ; + // $data['$your_invoice'] = ; + // $data['$quote'] = ; + // $data['$your_quote'] = ; + // $data['$invoice_issued_to'] = ; + // $data['$quote_issued_to'] = ; + // $data['$rate'] = ; + // $data['$hours'] = ; + // $data['$from'] = ; + // $data['$to'] = ; + // $data['$invoice_to'] = ; + // $data['$quote_to'] = ; + // $data['$details'] = ; + // $data['custom_label1'] = ['value' => '', 'label' => ctrans('texts.')]; + // $data['custom_label2'] = ['value' => '', 'label' => ctrans('texts.')]; + // $data['custom_label3'] = ['value' => '', 'label' => ctrans('texts.')]; + // $data['custom_label4'] = ['value' => '', 'label' => ctrans('texts.')]; + //$data['$blank'] = ; + //$data['$surcharge'] = ; + /* + $data['$tax_invoice'] = + $data['$tax_quote'] = + $data['$statement'] = ; + $data['$statement_date'] = ; + $data['$your_statement'] = ; + $data['$statement_issued_to'] = ; + $data['$statement_to'] = ; + $data['$credit_note'] = ; + $data['$credit_date'] = ; + $data['$credit_issued_to'] = ; + $data['$credit_to'] = ; + $data['$your_credit'] = ; + $data['$phone'] = ; + + $data['$outstanding'] = ; + $data['$invoice_due_date'] = ; + $data['$quote_due_date'] = ; + $data['$service'] = ; + $data['$product_key'] = ; + $data['$unit_cost'] = ; + $data['$custom_value1'] = ; + $data['$custom_value2'] = ; + $data['$delivery_note'] = ; + $data['$date'] = ; + $data['$method'] = ; + $data['$payment_date'] = ; + $data['$reference'] = ; + $data['$amount'] = ; + $data['$amount_paid'] =; + */ + + $arrKeysLength = array_map('strlen', array_keys($data)); + array_multisort($arrKeysLength, SORT_DESC, $data); + + return $data; + + } + +} \ No newline at end of file diff --git a/app/Utils/Traits/Payment/Refundable.php b/app/Utils/Traits/Payment/Refundable.php index c5663d2c2962..2b3038e7b5d8 100644 --- a/app/Utils/Traits/Payment/Refundable.php +++ b/app/Utils/Traits/Payment/Refundable.php @@ -1,4 +1,13 @@ =7.3", "ext-json": "*", - "anahkiasen/former": "^4.2", "asgrim/ofxparser": "^1.2", "codedge/laravel-selfupdater": "2.5.1", "composer/composer": "^1.10", @@ -35,7 +34,6 @@ "laravel/slack-notification-channel": "^2.0", "laravel/socialite": "^4.0", "laravel/tinker": "^1.0", - "laravelcollective/html": "^6", "league/fractal": "^0.17.0", "league/omnipay": "^3.0", "maennchen/zipstream-php": "^1.2", @@ -49,17 +47,18 @@ "stripe/stripe-php": "^7.0", "superbalist/laravel-google-cloud-storage": "^2.2", "webpatser/laravel-countries": "dev-master#75992ad", - "wildbit/postmark-php": "^2.6", - "yajra/laravel-datatables-html": "^4.0", - "yajra/laravel-datatables-oracle": "~9.0" + "fzaninotto/faker": "^1.4" }, "require-dev": { - "ext-json": "*", + "laravelcollective/html": "^6", + "wildbit/postmark-php": "^2.6", + "yajra/laravel-datatables-html": "^4.0", + "anahkiasen/former": "^4.2", + "yajra/laravel-datatables-oracle": "~9.0", "barryvdh/laravel-debugbar": "^3.2", "beyondcode/laravel-dump-server": "^1.0", "darkaonline/l5-swagger": "^6.0", "filp/whoops": "^2.0", - "fzaninotto/faker": "^1.4", "laravel/dusk": "^5.0", "mockery/mockery": "^1.0", "nunomaduro/collision": "^2.0", @@ -92,11 +91,14 @@ "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" ], "post-create-project-cmd": [ - "@php artisan key:generate --ansi" + "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"", + "@php artisan key:generate" ], "post-autoload-dump": [ "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", + "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"", "@php artisan package:discover --ansi", + "php artisan key:generate", "@php artisan storage:link" ] }, @@ -107,4 +109,4 @@ }, "minimum-stability": "dev", "prefer-stable": true -} +} \ No newline at end of file diff --git a/config/ninja.php b/config/ninja.php index a559015f115b..ef85b5d68b60 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -6,14 +6,14 @@ return [ 'license_url' => 'https://app.invoiceninja.com', 'production' => env('NINJA_PROD', false), 'license' => env('NINJA_LICENSE', ''), - 'app_name' => env('APP_NAME'), 'version_url' => 'https://raw.githubusercontent.com/invoiceninja/invoiceninja/v2/VERSION.txt', + 'app_name' => env('APP_NAME'), + 'app_env' => env('APP_ENV', 'local'), 'app_url' => env('APP_URL', ''), - 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), + 'app_domain' => env('APP_DOMAIN', ''), 'app_version' => '0.0.1', 'api_version' => '0.0.1', 'terms_version' => '1.0.1', - 'app_env' => env('APP_ENV', 'development'), 'api_secret' => env('API_SECRET', ''), 'google_maps_api_key' => env('GOOGLE_MAPS_API_KEY'), 'key_length' => 64, @@ -22,6 +22,7 @@ return [ 'daily_email_limit' => 300, 'error_email' => env('ERROR_EMAIL', ''), 'company_id' => 0, + 'hash_salt' => env('HASH_SALT', ''), 'environment' => env('NINJA_ENVIRONMENT', 'selfhost'), // 'hosted', 'development', 'selfhost', 'reseller' @@ -51,7 +52,7 @@ return [ 'datetime_format_id' => env('DEFAULT_DATETIME_FORMAT_ID', '1'), 'locale' => env('DEFAULT_LOCALE', 'en'), 'map_zoom' => env('DEFAULT_MAP_ZOOM', 10), - 'payment_terms' => env('DEFAULT_PAYMENT_TERMS', 1), + 'payment_terms' => env('DEFAULT_PAYMENT_TERMS', -1), 'military_time' => env('MILITARY_TIME', 0), 'first_day_of_week' => env('FIRST_DATE_OF_WEEK',0), 'first_month_of_year' => env('FIRST_MONTH_OF_YEAR', '2000-01-01') diff --git a/database/seeds/RandomDataSeeder.php b/database/seeds/RandomDataSeeder.php index f5d3a9d00aac..136939e70991 100644 --- a/database/seeds/RandomDataSeeder.php +++ b/database/seeds/RandomDataSeeder.php @@ -70,7 +70,7 @@ class RandomDataSeeder extends Seeder Eloquent::unguard(); - $faker = Faker\Factory::create(); + $faker = \Faker\Factory::create(); $account = factory(\App\Models\Account::class)->create(); $company = factory(\App\Models\Company::class)->create([ diff --git a/database/seeds/UsersTableSeeder.php b/database/seeds/UsersTableSeeder.php index f86c6bb6e381..f10cf88222ab 100644 --- a/database/seeds/UsersTableSeeder.php +++ b/database/seeds/UsersTableSeeder.php @@ -24,7 +24,7 @@ class UsersTableSeeder extends Seeder Eloquent::unguard(); - $faker = Faker\Factory::create(); + $faker = \Faker\Factory::create(); $account = factory(\App\Models\Account::class)->create(); $company = factory(\App\Models\Company::class)->create([ diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 086760834346..b6f9c8f2bcf9 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -3141,4 +3141,5 @@ return [ 'entity_number_placeholder' => ':entity # :entity_number', 'email_link_not_working' => 'If button above isn\'t working for you, please click on the link', 'credit_terms' => 'Credit Terms', + 'display_log' => 'Display Log', ]; diff --git a/resources/views/email/support/message.blade.php b/resources/views/email/support/message.blade.php index e4bf02b2a6c1..362b36bd04db 100644 --- a/resources/views/email/support/message.blade.php +++ b/resources/views/email/support/message.blade.php @@ -12,13 +12,14 @@ Header Title {!! str_replace('\n', '
', $system_info) !!} +@if(@count($laravel_log) > 0)
{{ ctrans('texts.display_log') }} @foreach($laravel_log as $log_line) {{ $log_line }}
@endforeach
- +@endif {{-- Subcopy --}} @isset($subcopy) @slot('subcopy') diff --git a/resources/views/pdf/stub.blade.php b/resources/views/pdf/stub.blade.php index c9528bb9922f..fce01e0cd494 100644 --- a/resources/views/pdf/stub.blade.php +++ b/resources/views/pdf/stub.blade.php @@ -2,7 +2,7 @@ {!! $includes !!} - {!! $header !!} + {!! $header !!} {!! $body !!} {!! $footer !!} diff --git a/routes/api.php b/routes/api.php index b15596c57ef7..ea26ddccbc92 100644 --- a/routes/api.php +++ b/routes/api.php @@ -144,6 +144,7 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a Route::group(['middleware' => ['api_db', 'locale'], 'prefix' => 'api/v1', 'as' => 'api.'], function () { Route::get('claim_license', 'LicenseController@index')->name('license.index'); + //Route::post('register_user', 'LicenseController@registerNinjaUser')->name('license.register_ninja_user'); }); diff --git a/routes/web.php b/routes/web.php index 7ee56d50f85d..c47ad0ac266b 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,30 +1,11 @@ name('login'); -// Route::post('login', 'Auth\LoginController@login'); -// Route::post('logout', 'Auth\LoginController@logout')->name('logout'); - /* * Signup Routes */ Route::get('/', 'BaseController@flutterRoute')->middleware('guest'); - - -Route::group(['middleware' => ['invite_db'], 'prefix' => '', 'as' => ''], function () { - - /*Invitation catches*/ - - - -}); - - -// Route::get('signup', 'AccountController@index')->name('signup'); -// Route::post('signup', 'AccountController@store')->name('signup.submit'); +Route::get('setup', 'SetupController@index')->middleware('guest'); +Route::post('setup', 'SetupController@doSetup')->middleware('guest'); /* * Password Reset Routes... @@ -42,57 +23,6 @@ Route::post('password/reset', 'Auth\ResetPasswordController@reset')->name('passw // Route::get('auth/{provider}', 'Auth\LoginController@redirectToProvider'); // Route::get('auth/{provider}/create', 'Auth\LoginController@redirectToProviderAndCreate'); -/* - * Authenticated User Routes - */ -/* -Route::group(['middleware' => ['auth:user', 'web_db']], function () { - - Route::resource('dashboard', 'DashboardController'); // name = (dashboard. index / create / show / update / destroy / edit - - Route::get('logout', 'Auth\LoginController@logout')->name('user.logout'); - - Route::resource('invoices', 'InvoiceController'); // name = (invoices. index / create / show / update / destroy / edit - - Route::post('invoices/bulk', 'InvoiceController@bulk')->name('invoices.bulk'); - - Route::resource('quotes', 'QuoteController'); // name = (quotes. index / create / show / update / destroy / edit - - Route::post('quotes/bulk', 'QuoteController@bulk')->name('quotes.bulk'); - - Route::resource('recurring_invoices', 'RecurringInvoiceController'); // name = (recurring_invoices. index / create / show / update / destroy / edit - - Route::post('recurring_invoices/bulk', 'RecurringInvoiceController@bulk')->name('recurring_invoices.bulk'); - - Route::resource('clients', 'ClientController'); // name = (clients. index / create / show / update / destroy / edit - - Route::post('clients/bulk', 'ClientController@bulk')->name('clients.bulk'); - - Route::resource('client_statement', 'ClientStatementController@statement'); // name = (client_statement. index / create / show / update / destroy / edit - - Route::resource('tasks', 'TaskController'); // name = (tasks. index / create / show / update / destroy / edit - - Route::post('tasks/bulk', 'TaskController@bulk')->name('tasks.bulk'); - - Route::resource('payments', 'PaymentController'); // name = (payments. index / create / show / update / destroy / edit - - Route::post('payments/bulk', 'PaymentController@bulk')->name('payments.bulk'); - - Route::resource('credits', 'CreditController'); // name = (credits. index / create / show / update / destroy / edit - - Route::post('credits/bulk', 'CreditController@bulk')->name('credits.bulk'); - - Route::resource('expenses', 'ExpenseController'); // name = (expenses. index / create / show / update / destroy / edit - - Route::post('expenses/bulk', 'ExpenseController@bulk')->name('expenses.bulk'); - - Route::resource('user', 'UserProfileController'); // name = (clients. index / create / show / update / destroy / edit - - Route::get('settings', 'SettingsController@index')->name('user.settings'); - - -}); -*/ /* * Inbound routes requiring DB Lookup */ @@ -100,11 +30,4 @@ Route::group(['middleware' => ['url_db']], function () { Route::get('/user/confirm/{confirmation_code}', 'UserController@confirm'); -}); - - - -/* - * Injects users translation strings in json format for frontend consumption. - */ -//Route::get('js/lang.js', 'TranslationController@index')->name('assets.lang'); \ No newline at end of file +}); \ No newline at end of file diff --git a/tests/Unit/CompareObjectTest.php b/tests/Unit/CompareObjectTest.php index 388521b93804..2cea644779df 100644 --- a/tests/Unit/CompareObjectTest.php +++ b/tests/Unit/CompareObjectTest.php @@ -47,7 +47,7 @@ class CompareObjectTest extends TestCase $this->assertEquals($build_client_settings->timezone_id, 1); $this->assertEquals($build_client_settings->language_id, 1); - $this->assertEquals($build_client_settings->payment_terms, 1); + $this->assertEquals($build_client_settings->payment_terms, -1); } public function testDirectClientSettingsBuild() @@ -56,7 +56,7 @@ class CompareObjectTest extends TestCase $this->assertEquals($settings->timezone_id, 1); $this->assertEquals($settings->language_id, 1); - $this->assertEquals($settings->payment_terms, 1); + $this->assertEquals($settings->payment_terms, -1); $this->assertFalse($settings->send_portal_password); } diff --git a/tests/Unit/SystemHealthTest.php b/tests/Unit/SystemHealthTest.php index 6e9b9c099e41..d0654b0773d9 100644 --- a/tests/Unit/SystemHealthTest.php +++ b/tests/Unit/SystemHealthTest.php @@ -36,8 +36,7 @@ class SystemHealthTest extends TestCase $this->assertTrue($results['extensions'][2]['curl']); $this->assertTrue($results['extensions'][3]['zip']); - -// $this->assertTrue($results['dbs'][0]['db-ninja-01']); +// \Log::error(print_r($results,1)); } }