mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Exporting migration data via HTTP (v1) (#3364)
* Migration: Option to select the migration type * Migration: Logic for redirecting based on steps * Work for migrations: - Added authentication view, service - Account connecting - Scaffold services - Companies service - (wip) Sending data to v2 * Migration: Sending migration file * Wrap up the migration first stage * Split company per request / no bundle Co-authored-by: David Bomba <turbo124@gmail.com>
This commit is contained in:
parent
8020204c8d
commit
ff455c8ed9
@ -17,12 +17,37 @@ use App\Models\Product;
|
|||||||
use App\Models\TaxRate;
|
use App\Models\TaxRate;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
use App\Http\Controllers\BaseController;
|
||||||
|
use App\Http\Requests\MigrationAuthRequest;
|
||||||
|
use App\Http\Requests\MigrationCompaniesRequest;
|
||||||
|
use App\Http\Requests\MigrationEndpointRequest;
|
||||||
|
use App\Http\Requests\MigrationTypeRequest;
|
||||||
|
use App\Models\Document;
|
||||||
|
use App\Services\Migration\AuthService;
|
||||||
|
use App\Services\Migration\CompanyService;
|
||||||
|
use App\Services\Migration\CompleteService;
|
||||||
use Illuminate\Support\Facades\Crypt;
|
use Illuminate\Support\Facades\Crypt;
|
||||||
|
|
||||||
class StepsController extends BaseController
|
class StepsController extends BaseController
|
||||||
{
|
{
|
||||||
private $account;
|
private $account;
|
||||||
|
|
||||||
|
private $access = [
|
||||||
|
'auth' => [
|
||||||
|
'steps' => ['MIGRATION_TYPE'],
|
||||||
|
'redirect' => '/migration/start',
|
||||||
|
],
|
||||||
|
'endpoint' => [
|
||||||
|
'steps' => ['MIGRATION_TYPE'],
|
||||||
|
'redirect' => '/migration/start',
|
||||||
|
],
|
||||||
|
'companies' => [
|
||||||
|
'steps' => ['MIGRATION_TYPE', 'MIGRATION_ACCOUNT_TOKEN'],
|
||||||
|
'redirect' => '/migration/auth',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
*/
|
*/
|
||||||
@ -44,12 +69,142 @@ class StepsController extends BaseController
|
|||||||
return view('migration.download');
|
return view('migration.download');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function handleType(MigrationTypeRequest $request)
|
||||||
|
{
|
||||||
|
session()->put('MIGRATION_TYPE', $request->option);
|
||||||
|
|
||||||
|
if($request->option == 0)
|
||||||
|
return redirect('/migration/auth');
|
||||||
|
|
||||||
|
return redirect('/migration/endpoint');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function endpoint()
|
||||||
|
{
|
||||||
|
if($this->shouldGoBack('endpoint'))
|
||||||
|
return redirect($this->access['endpoint']['redirect']);
|
||||||
|
|
||||||
|
return view('migration.endpoint');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleEndpoint(MigrationEndpointRequest $request)
|
||||||
|
{
|
||||||
|
if($this->shouldGoBack('endpoint'))
|
||||||
|
return redirect($this->access['endpoint']['redirect']);
|
||||||
|
|
||||||
|
session()->put('MIGRATION_ENDPOINT', $request->endpoint);
|
||||||
|
|
||||||
|
return redirect('/migration/auth');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function auth()
|
||||||
|
{
|
||||||
|
if($this->shouldGoBack('auth'))
|
||||||
|
return redirect($this->access['auth']['redirect']);
|
||||||
|
|
||||||
|
return view('migration.auth');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleAuth(MigrationAuthRequest $request)
|
||||||
|
{
|
||||||
|
if($this->shouldGoBack('auth')) {
|
||||||
|
return redirect($this->access['auth']['redirect']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$authentication = (new AuthService($request->email, $request->password))
|
||||||
|
->endpoint(session('MIGRATION_ENDPOINT'))
|
||||||
|
->start();
|
||||||
|
|
||||||
|
if($authentication->isSuccessful()) {
|
||||||
|
session()->put('MIGRATION_ACCOUNT_TOKEN', $authentication->getAccountToken());
|
||||||
|
|
||||||
|
return redirect('/migration/companies');
|
||||||
|
}
|
||||||
|
|
||||||
|
return back()->with('responseErrors', $authentication->getErrors());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function companies()
|
||||||
|
{
|
||||||
|
if($this->shouldGoBack('companies'))
|
||||||
|
return redirect($this->access['companies']['redirect']);
|
||||||
|
|
||||||
|
$companyService = (new CompanyService(session('MIGRATION_ACCOUNT_TOKEN')))
|
||||||
|
->endpoint(session('MIGRATION_ENDPOINT'))
|
||||||
|
->start();
|
||||||
|
|
||||||
|
if($companyService->isSuccessful()) {
|
||||||
|
return view('migration.companies', ['companies' => $companyService->getCompanies()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'message' => 'Oops, looks like something failed. Please try again.'
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleCompanies(MigrationCompaniesRequest $request)
|
||||||
|
{
|
||||||
|
if($this->shouldGoBack('companies'))
|
||||||
|
return redirect($this->access['companies']['redirect']);
|
||||||
|
|
||||||
|
$successful = false;
|
||||||
|
|
||||||
|
foreach ($request->companies as $company) {
|
||||||
|
$completeService = (new CompleteService(session('MIGRATION_ACCOUNT_TOKEN')))
|
||||||
|
->file($this->getMigrationFile())
|
||||||
|
->company($company)
|
||||||
|
->endpoint(session('MIGRATION_ENDPOINT'))
|
||||||
|
->start();
|
||||||
|
|
||||||
|
if($completeService->isSuccessful()) {
|
||||||
|
$successful = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$successful = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($successful) {
|
||||||
|
return view('migration.completed');
|
||||||
|
}
|
||||||
|
|
||||||
|
return response([
|
||||||
|
'message' => 'Failed',
|
||||||
|
'errors' => $completeService->getErrors(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function completed()
|
||||||
|
{
|
||||||
|
return view('migration.completed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ==================================
|
||||||
|
* Rest of functions that are used as 'actions', not controller methods.
|
||||||
|
* ==================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
public function shouldGoBack(string $step)
|
||||||
|
{
|
||||||
|
$redirect = true;
|
||||||
|
|
||||||
|
foreach ($this->access[$step]['steps'] as $step) {
|
||||||
|
if(session()->has($step)) {
|
||||||
|
$redirect = false;
|
||||||
|
} else {
|
||||||
|
$redirect = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $redirect;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle data downloading for the migration.
|
* Handle data downloading for the migration.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function handleDownload()
|
public function getMigrationFile()
|
||||||
{
|
{
|
||||||
$this->account = Auth::user()->account;
|
$this->account = Auth::user()->account;
|
||||||
|
|
||||||
@ -82,14 +237,11 @@ class StepsController extends BaseController
|
|||||||
$zip->addFromString('migration.json', json_encode($data, JSON_PRETTY_PRINT));
|
$zip->addFromString('migration.json', json_encode($data, JSON_PRETTY_PRINT));
|
||||||
$zip->close();
|
$zip->close();
|
||||||
|
|
||||||
header('Content-Type: application/zip');
|
// header('Content-Type: application/zip');
|
||||||
header('Content-Length: ' . filesize($file));
|
// header('Content-Length: ' . filesize($file));
|
||||||
header("Content-Disposition: attachment; filename={$fileName}.zip");
|
// header("Content-Disposition: attachment; filename={$fileName}.zip");
|
||||||
|
|
||||||
readfile($file);
|
return $file;
|
||||||
unlink($file);
|
|
||||||
|
|
||||||
return response()->json($data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
31
app/Http/Requests/MigrationAuthRequest.php
Normal file
31
app/Http/Requests/MigrationAuthRequest.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class MigrationAuthRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'email' => 'required|email',
|
||||||
|
'password' => 'required',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
30
app/Http/Requests/MigrationCompaniesRequest.php
Normal file
30
app/Http/Requests/MigrationCompaniesRequest.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class MigrationCompaniesRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'companies' => 'required',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
30
app/Http/Requests/MigrationEndpointRequest.php
Normal file
30
app/Http/Requests/MigrationEndpointRequest.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class MigrationEndpointRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'endpoint' => 'required|url',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
30
app/Http/Requests/MigrationTypeRequest.php
Normal file
30
app/Http/Requests/MigrationTypeRequest.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class MigrationTypeRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'option' => 'required|in:0,1',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
95
app/Services/Migration/AuthService.php
Normal file
95
app/Services/Migration/AuthService.php
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\Migration;
|
||||||
|
|
||||||
|
use Unirest\Request;
|
||||||
|
use Unirest\Request\Body;
|
||||||
|
|
||||||
|
class AuthService
|
||||||
|
{
|
||||||
|
protected $username;
|
||||||
|
protected $password;
|
||||||
|
protected $endpoint = 'https://app.invoiceninja.com';
|
||||||
|
protected $uri = '/api/v1/login?include=token';
|
||||||
|
protected $errors = [];
|
||||||
|
protected $token;
|
||||||
|
protected $isSuccessful;
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(string $username, string $password)
|
||||||
|
{
|
||||||
|
$this->username = $username;
|
||||||
|
$this->password = $password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function endpoint(string $endpoint)
|
||||||
|
{
|
||||||
|
$this->endpoint = $endpoint;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function start()
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'email' => $this->username,
|
||||||
|
'password' => $this->password,
|
||||||
|
];
|
||||||
|
|
||||||
|
$body = Body::json($data);
|
||||||
|
|
||||||
|
$response = Request::post($this->getUrl(), $this->getHeaders(), $body);
|
||||||
|
|
||||||
|
if ($response->code == 200) {
|
||||||
|
$this->isSuccessful = true;
|
||||||
|
$this->token = $response->body->data[0]->token->token;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($response->code, [401, 422, 500])) {
|
||||||
|
$this->isSuccessful = false;
|
||||||
|
$this->processErrors($response->body);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isSuccessful()
|
||||||
|
{
|
||||||
|
return $this->isSuccessful;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAccountToken()
|
||||||
|
{
|
||||||
|
if ($this->isSuccessful) {
|
||||||
|
return $this->token;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getErrors()
|
||||||
|
{
|
||||||
|
return $this->errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getHeaders()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'X-Requested-With' => 'XMLHttpRequest',
|
||||||
|
'Content-Type' => 'application/json',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUrl()
|
||||||
|
{
|
||||||
|
return $this->endpoint . $this->uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processErrors($errors)
|
||||||
|
{
|
||||||
|
$array = (array) $errors;
|
||||||
|
|
||||||
|
$this->errors = $array;
|
||||||
|
}
|
||||||
|
}
|
89
app/Services/Migration/CompanyService.php
Normal file
89
app/Services/Migration/CompanyService.php
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\Migration;
|
||||||
|
|
||||||
|
use Unirest\Request;
|
||||||
|
use Unirest\Request\Body;
|
||||||
|
|
||||||
|
class CompanyService
|
||||||
|
{
|
||||||
|
protected $token;
|
||||||
|
protected $endpoint = 'https://app.invoiceninja.com';
|
||||||
|
protected $uri = '/api/v1/companies';
|
||||||
|
protected $errors = [];
|
||||||
|
protected $isSuccessful;
|
||||||
|
protected $companies = [];
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(string $token)
|
||||||
|
{
|
||||||
|
$this->token = $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function endpoint(string $endpoint)
|
||||||
|
{
|
||||||
|
$this->endpoint = $endpoint;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function start()
|
||||||
|
{
|
||||||
|
$response = Request::get($this->getUrl(), $this->getHeaders());
|
||||||
|
|
||||||
|
if ($response->code == 200) {
|
||||||
|
$this->isSuccessful = true;
|
||||||
|
|
||||||
|
foreach($response->body->data as $company) {
|
||||||
|
$this->companies[] = $company;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($response->code, [401, 422, 500])) {
|
||||||
|
$this->isSuccessful = false;
|
||||||
|
$this->processErrors($response->body);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isSuccessful()
|
||||||
|
{
|
||||||
|
return $this->isSuccessful;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCompanies()
|
||||||
|
{
|
||||||
|
if ($this->isSuccessful) {
|
||||||
|
return $this->companies;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getErrors()
|
||||||
|
{
|
||||||
|
return $this->errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getHeaders()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'X-Requested-With' => 'XMLHttpRequest',
|
||||||
|
'X-Api-Token' => $this->token,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUrl()
|
||||||
|
{
|
||||||
|
return $this->endpoint . $this->uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processErrors($errors)
|
||||||
|
{
|
||||||
|
$array = (array) $errors;
|
||||||
|
|
||||||
|
$this->errors = $array;
|
||||||
|
}
|
||||||
|
}
|
98
app/Services/Migration/CompleteService.php
Normal file
98
app/Services/Migration/CompleteService.php
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\Migration;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Unirest\Request;
|
||||||
|
use Unirest\Request\Body;
|
||||||
|
|
||||||
|
class CompleteService
|
||||||
|
{
|
||||||
|
protected $token;
|
||||||
|
protected $company;
|
||||||
|
protected $file;
|
||||||
|
protected $endpoint = 'https://app.invoiceninja.com';
|
||||||
|
protected $uri = '/api/v1/migration/start/';
|
||||||
|
protected $errors = [];
|
||||||
|
protected $isSuccessful;
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(string $token)
|
||||||
|
{
|
||||||
|
$this->token = $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function file($file)
|
||||||
|
{
|
||||||
|
$this->file = $file;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function company($company)
|
||||||
|
{
|
||||||
|
$this->company = $company;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function endpoint(string $endpoint)
|
||||||
|
{
|
||||||
|
$this->endpoint = $endpoint;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function start()
|
||||||
|
{
|
||||||
|
$body = [
|
||||||
|
'migration' => \Unirest\Request\Body::file($this->file, 'application/zip'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = Request::post($this->getUrl(), $this->getHeaders(), $body);
|
||||||
|
|
||||||
|
if ($response->code == 200) {
|
||||||
|
$this->isSuccessful = true;
|
||||||
|
$this->deleteFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($response->code, [401, 422, 500])) {
|
||||||
|
$this->isSuccessful = false;
|
||||||
|
$this->errors = [
|
||||||
|
'Oops, something went wrong. Migration can\'t be processed at the moment.',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isSuccessful()
|
||||||
|
{
|
||||||
|
return $this->isSuccessful;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getErrors()
|
||||||
|
{
|
||||||
|
return $this->errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getHeaders()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'X-Requested-With' => 'XMLHttpRequest',
|
||||||
|
'X-Api-Token' => $this->token,
|
||||||
|
'Content-Type' => 'multipart/form-data',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getUrl()
|
||||||
|
{
|
||||||
|
return $this->endpoint . $this->uri . $this->company;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteFile()
|
||||||
|
{
|
||||||
|
Storage::delete($this->file);
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,8 @@
|
|||||||
"php": ">=7.0.0",
|
"php": ">=7.0.0",
|
||||||
"ext-gd": "*",
|
"ext-gd": "*",
|
||||||
"ext-gmp": "*",
|
"ext-gmp": "*",
|
||||||
|
"ext-json": "*",
|
||||||
|
"ext-zip": "*",
|
||||||
"anahkiasen/former": "4.*",
|
"anahkiasen/former": "4.*",
|
||||||
"asgrim/ofxparser": "^1.1",
|
"asgrim/ofxparser": "^1.1",
|
||||||
"bacon/bacon-qr-code": "^1.0",
|
"bacon/bacon-qr-code": "^1.0",
|
||||||
@ -51,6 +53,7 @@
|
|||||||
"league/flysystem-rackspace": "~1.0",
|
"league/flysystem-rackspace": "~1.0",
|
||||||
"league/fractal": "0.13.*",
|
"league/fractal": "0.13.*",
|
||||||
"maatwebsite/excel": "~2.0",
|
"maatwebsite/excel": "~2.0",
|
||||||
|
"mashape/unirest-php": "^3.0",
|
||||||
"mpdf/mpdf": "7.1.7",
|
"mpdf/mpdf": "7.1.7",
|
||||||
"nesbot/carbon": "^1.26",
|
"nesbot/carbon": "^1.26",
|
||||||
"nwidart/laravel-modules": "2.0.*",
|
"nwidart/laravel-modules": "2.0.*",
|
||||||
@ -68,9 +71,7 @@
|
|||||||
"webpatser/laravel-countries": "dev-master#75992ad",
|
"webpatser/laravel-countries": "dev-master#75992ad",
|
||||||
"websight/l5-google-cloud-storage": "dev-master",
|
"websight/l5-google-cloud-storage": "dev-master",
|
||||||
"wepay/php-sdk": "^0.2",
|
"wepay/php-sdk": "^0.2",
|
||||||
"wildbit/postmark-php": "^2.5",
|
"wildbit/postmark-php": "^2.5"
|
||||||
"ext-json": "*",
|
|
||||||
"ext-zip": "*"
|
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"symfony/dom-crawler": "~3.1",
|
"symfony/dom-crawler": "~3.1",
|
||||||
|
66
composer.lock
generated
66
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "9124fcb26c4f7a15410a4b6899151938",
|
"content-hash": "5ebbda0ec4f775dcd10261da641f4c27",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "abdala/omnipay-pagseguro",
|
"name": "abdala/omnipay-pagseguro",
|
||||||
@ -561,12 +561,12 @@
|
|||||||
"version": "v0.9.3",
|
"version": "v0.9.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/barryvdh/laravel-cors.git",
|
"url": "https://github.com/fruitcake/laravel-cors.git",
|
||||||
"reference": "2551489de60486471434b0c7050f7fc65f9c9119"
|
"reference": "2551489de60486471434b0c7050f7fc65f9c9119"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/barryvdh/laravel-cors/zipball/2551489de60486471434b0c7050f7fc65f9c9119",
|
"url": "https://api.github.com/repos/fruitcake/laravel-cors/zipball/2551489de60486471434b0c7050f7fc65f9c9119",
|
||||||
"reference": "2551489de60486471434b0c7050f7fc65f9c9119",
|
"reference": "2551489de60486471434b0c7050f7fc65f9c9119",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
@ -1274,6 +1274,7 @@
|
|||||||
],
|
],
|
||||||
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
|
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
|
||||||
"homepage": "https://github.com/container-interop/container-interop",
|
"homepage": "https://github.com/container-interop/container-interop",
|
||||||
|
"abandoned": "psr/container",
|
||||||
"time": "2017-02-14T19:40:03+00:00"
|
"time": "2017-02-14T19:40:03+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -5124,6 +5125,52 @@
|
|||||||
],
|
],
|
||||||
"time": "2018-03-09T13:14:19+00:00"
|
"time": "2018-03-09T13:14:19+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "mashape/unirest-php",
|
||||||
|
"version": "v3.0.4",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Mashape/unirest-php.git",
|
||||||
|
"reference": "842c0f242dfaaf85f16b72e217bf7f7c19ab12cb"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Mashape/unirest-php/zipball/842c0f242dfaaf85f16b72e217bf7f7c19ab12cb",
|
||||||
|
"reference": "842c0f242dfaaf85f16b72e217bf7f7c19ab12cb",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-curl": "*",
|
||||||
|
"php": ">=5.4.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"codeclimate/php-test-reporter": "0.1.*",
|
||||||
|
"phpunit/phpunit": "~4.4"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-json": "Allows using JSON Bodies for sending and parsing requests"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": {
|
||||||
|
"Unirest\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"description": "Unirest PHP",
|
||||||
|
"homepage": "https://github.com/Mashape/unirest-php",
|
||||||
|
"keywords": [
|
||||||
|
"client",
|
||||||
|
"curl",
|
||||||
|
"http",
|
||||||
|
"https",
|
||||||
|
"rest"
|
||||||
|
],
|
||||||
|
"time": "2016-08-11T17:49:21+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "maximebf/debugbar",
|
"name": "maximebf/debugbar",
|
||||||
"version": "v1.14.1",
|
"version": "v1.14.1",
|
||||||
@ -5571,6 +5618,7 @@
|
|||||||
"cron",
|
"cron",
|
||||||
"schedule"
|
"schedule"
|
||||||
],
|
],
|
||||||
|
"abandoned": "dragonmantank/cron-expression",
|
||||||
"time": "2017-01-23T04:29:33+00:00"
|
"time": "2017-01-23T04:29:33+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -11352,6 +11400,7 @@
|
|||||||
"escaper",
|
"escaper",
|
||||||
"zf2"
|
"zf2"
|
||||||
],
|
],
|
||||||
|
"abandoned": "laminas/laminas-escaper",
|
||||||
"time": "2016-06-30T19:48:38+00:00"
|
"time": "2016-06-30T19:48:38+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -11405,6 +11454,7 @@
|
|||||||
"zend",
|
"zend",
|
||||||
"zf"
|
"zf"
|
||||||
],
|
],
|
||||||
|
"abandoned": "laminas/laminas-http",
|
||||||
"time": "2017-10-13T12:06:24+00:00"
|
"time": "2017-10-13T12:06:24+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -11460,6 +11510,7 @@
|
|||||||
"json",
|
"json",
|
||||||
"zf2"
|
"zf2"
|
||||||
],
|
],
|
||||||
|
"abandoned": "laminas/laminas-json",
|
||||||
"time": "2016-02-04T21:20:26+00:00"
|
"time": "2016-02-04T21:20:26+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -11504,6 +11555,7 @@
|
|||||||
"loader",
|
"loader",
|
||||||
"zf2"
|
"zf2"
|
||||||
],
|
],
|
||||||
|
"abandoned": "laminas/laminas-loader",
|
||||||
"time": "2015-06-03T14:05:47+00:00"
|
"time": "2015-06-03T14:05:47+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -11549,6 +11601,7 @@
|
|||||||
"stdlib",
|
"stdlib",
|
||||||
"zf2"
|
"zf2"
|
||||||
],
|
],
|
||||||
|
"abandoned": "laminas/laminas-stdlib",
|
||||||
"time": "2016-09-13T14:38:50+00:00"
|
"time": "2016-09-13T14:38:50+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -11596,6 +11649,7 @@
|
|||||||
"uri",
|
"uri",
|
||||||
"zf2"
|
"zf2"
|
||||||
],
|
],
|
||||||
|
"abandoned": "laminas/laminas-uri",
|
||||||
"time": "2016-02-17T22:38:51+00:00"
|
"time": "2016-02-17T22:38:51+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -11667,6 +11721,7 @@
|
|||||||
"validator",
|
"validator",
|
||||||
"zf2"
|
"zf2"
|
||||||
],
|
],
|
||||||
|
"abandoned": "laminas/laminas-validator",
|
||||||
"time": "2018-02-01T17:05:33+00:00"
|
"time": "2018-02-01T17:05:33+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -11753,6 +11808,7 @@
|
|||||||
"push",
|
"push",
|
||||||
"zf2"
|
"zf2"
|
||||||
],
|
],
|
||||||
|
"abandoned": true,
|
||||||
"time": "2017-01-17T13:57:50+00:00"
|
"time": "2017-01-17T13:57:50+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -13626,7 +13682,9 @@
|
|||||||
"platform": {
|
"platform": {
|
||||||
"php": ">=7.0.0",
|
"php": ">=7.0.0",
|
||||||
"ext-gd": "*",
|
"ext-gd": "*",
|
||||||
"ext-gmp": "*"
|
"ext-gmp": "*",
|
||||||
|
"ext-json": "*",
|
||||||
|
"ext-zip": "*"
|
||||||
},
|
},
|
||||||
"platform-dev": []
|
"platform-dev": []
|
||||||
}
|
}
|
||||||
|
@ -3273,7 +3273,6 @@ $LANG = array(
|
|||||||
'start_the_migration' => 'Start the migration',
|
'start_the_migration' => 'Start the migration',
|
||||||
'migration' => 'Migration',
|
'migration' => 'Migration',
|
||||||
'welcome_to_the_new_version' => 'Welcome to the new version of Invoice Ninja',
|
'welcome_to_the_new_version' => 'Welcome to the new version of Invoice Ninja',
|
||||||
'next_step_data_download' => 'At the next step, we\'ll let you download your data for the migration.',
|
|
||||||
'download_data' => 'Press button below to download the data.',
|
'download_data' => 'Press button below to download the data.',
|
||||||
'migration_import' => 'Awesome! Now you are ready to import your migration. Go to your new installation to import your data',
|
'migration_import' => 'Awesome! Now you are ready to import your migration. Go to your new installation to import your data',
|
||||||
'continue' => 'Continue',
|
'continue' => 'Continue',
|
||||||
|
32
resources/views/migration/auth.blade.php
Normal file
32
resources/views/migration/auth.blade.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
@extends('header')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
@parent
|
||||||
|
@include('accounts.nav', ['selected' => ACCOUNT_MANAGEMENT])
|
||||||
|
|
||||||
|
@include('migration.includes.errors')
|
||||||
|
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">{!! trans('texts.welcome_to_the_new_version') !!}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<h4>Let's continue with authentication.</h4>
|
||||||
|
<form action="/migration/auth" method="post" id="auth-form">
|
||||||
|
{{ csrf_field() }}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="email">E-mail address</label>
|
||||||
|
<input type="email" name="email" class="form form-control">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<input type="password" name="password" class="form form-control">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="panel-footer text-right">
|
||||||
|
<button onclick="document.getElementById('auth-form').submit();" class="btn btn-primary">{!! trans('texts.continue') !!}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@stop
|
32
resources/views/migration/companies.blade.php
Normal file
32
resources/views/migration/companies.blade.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
@extends('header')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
@parent
|
||||||
|
@include('accounts.nav', ['selected' => ACCOUNT_MANAGEMENT])
|
||||||
|
|
||||||
|
@include('migration.includes.errors')
|
||||||
|
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">{!! trans('texts.welcome_to_the_new_version') !!}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<h4>Awesome! Please select the company you would like to apply migration.</h4>
|
||||||
|
<form action="/migration/companies" method="post" id="auth-form">
|
||||||
|
{{ csrf_field() }}
|
||||||
|
|
||||||
|
@foreach($companies as $company)
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" name="companies[]" id="company1" value="{{ $company->id }}" checked>
|
||||||
|
<label class="form-check-label" for="company1">
|
||||||
|
Name: {{ $company->settings->name }} ID: {{ $company->id }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="panel-footer text-right">
|
||||||
|
<button onclick="document.getElementById('auth-form').submit();" class="btn btn-primary">{!! trans('texts.continue') !!}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@stop
|
17
resources/views/migration/completed.blade.php
Normal file
17
resources/views/migration/completed.blade.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@extends('header')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
@parent
|
||||||
|
@include('accounts.nav', ['selected' => ACCOUNT_MANAGEMENT])
|
||||||
|
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">{!! trans('texts.welcome_to_the_new_version') !!}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
Completed, thanks!
|
||||||
|
<!-- Note: This message needs edit, like next instructions, etc. -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@stop
|
28
resources/views/migration/endpoint.blade.php
Normal file
28
resources/views/migration/endpoint.blade.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
@extends('header')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
@parent
|
||||||
|
@include('accounts.nav', ['selected' => ACCOUNT_MANAGEMENT])
|
||||||
|
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">{!! trans('texts.welcome_to_the_new_version') !!}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<h4>We need to know the link of your application.</h4>
|
||||||
|
<form action="/migration/endpoint" method="post" id="input-endpoint-form">
|
||||||
|
{{ csrf_field() }}
|
||||||
|
<div class="form-check">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="endpoint">Link</label>
|
||||||
|
<input type="text" class="form-control" name="endpoint" required placeholder="Example: https://myinvoiceninja.com">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="panel-footer text-right">
|
||||||
|
<button onclick="document.getElementById('input-endpoint-form').submit();" class="btn btn-primary">{!! trans('texts.continue') !!}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@stop
|
9
resources/views/migration/includes/errors.blade.php
Normal file
9
resources/views/migration/includes/errors.blade.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
@if(session('responseErrors'))
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<ul>
|
||||||
|
@foreach(session('responseErrors') as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
@ -9,10 +9,28 @@
|
|||||||
<h3 class="panel-title">{!! trans('texts.welcome_to_the_new_version') !!}</h3>
|
<h3 class="panel-title">{!! trans('texts.welcome_to_the_new_version') !!}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<h4>{!! trans('texts.next_step_data_download') !!}</h4>
|
<h4>In order to start the migration, we need to know where do you want to migrate.</h4>
|
||||||
|
<form action="/migration/type" method="post" id="select-type-form">
|
||||||
|
{{ csrf_field() }}
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="option" id="option1" value="0" checked>
|
||||||
|
<label class="form-check-label" for="option1">
|
||||||
|
Hosted
|
||||||
|
</label>
|
||||||
|
<p>If you chose 'hosted', we will migrate your data to official Invoice Ninja servers & take care of server handling.</p>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="option" id="option2" value="1">
|
||||||
|
<label class="form-check-label" for="option2">
|
||||||
|
Self-hosted
|
||||||
|
</label>
|
||||||
|
<p>By choosing the 'self-hosted', you are the one in charge of servers.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-footer text-right">
|
<div class="panel-footer text-right">
|
||||||
<a href="/migration/download" class="btn btn-primary">{!! trans('texts.continue') !!}</a>
|
<button onclick="document.getElementById('select-type-form').submit();" class="btn btn-primary">{!! trans('texts.continue') !!}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -149,9 +149,16 @@ Route::group(['middleware' => ['lookup:user', 'auth:user']], function () {
|
|||||||
Route::post('settings/enable_two_factor', 'TwoFactorController@enableTwoFactor');
|
Route::post('settings/enable_two_factor', 'TwoFactorController@enableTwoFactor');
|
||||||
|
|
||||||
Route::get('migration/start', 'Migration\StepsController@start');
|
Route::get('migration/start', 'Migration\StepsController@start');
|
||||||
|
Route::post('migration/type', 'Migration\StepsController@handleType');
|
||||||
Route::get('migration/download', 'Migration\StepsController@download');
|
Route::get('migration/download', 'Migration\StepsController@download');
|
||||||
Route::post('migration/download', 'Migration\StepsController@handleDownload');
|
Route::post('migration/download', 'Migration\StepsController@handleDownload');
|
||||||
|
Route::get('migration/endpoint', 'Migration\StepsController@endpoint');
|
||||||
|
Route::post('migration/endpoint', 'Migration\StepsController@handleEndpoint');
|
||||||
|
Route::get('migration/auth', 'Migration\StepsController@auth');
|
||||||
|
Route::post('migration/auth', 'Migration\StepsController@handleAuth');
|
||||||
|
Route::get('migration/companies', 'Migration\StepsController@companies');
|
||||||
|
Route::post('migration/companies', 'Migration\StepsController@handleCompanies');
|
||||||
|
Route::get('migration/completed', 'Migration\StepsController@completed');
|
||||||
|
|
||||||
Route::get('migration/import', 'Migration\StepsController@import');
|
Route::get('migration/import', 'Migration\StepsController@import');
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user