11
.github/workflows/release.yml
vendored
@ -48,11 +48,12 @@ jobs:
|
||||
run: |
|
||||
sudo rm -rf bootstrap/cache/*
|
||||
sudo rm -rf node_modules
|
||||
- name: Prune Git History
|
||||
run: |
|
||||
sudo git gc
|
||||
sudo git gc --aggressive
|
||||
sudo git prune
|
||||
sudo rm -rf .git
|
||||
# - name: Prune Git History
|
||||
# run: |
|
||||
# sudo git gc
|
||||
# sudo git gc --aggressive
|
||||
# sudo git prune
|
||||
- name: Build project # This would actually build your project, using zip for an example artifact
|
||||
run: |
|
||||
zip -r ./invoiceninja.zip .* -x "../*"
|
||||
|
@ -1 +1 @@
|
||||
5.1.48
|
||||
5.1.49
|
31
app/Factory/ClientGatewayTokenFactory.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Factory;
|
||||
|
||||
use App\Models\ClientGatewayToken;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ClientGatewayTokenFactory
|
||||
{
|
||||
public static function create(int $company_id) :ClientGatewayToken
|
||||
{
|
||||
$client_gateway_token = new ClientGatewayToken;
|
||||
$client_gateway_token->company_id = $company_id;
|
||||
$client_gateway_token->is_default = false;
|
||||
$client_gateway_token->meta = '';
|
||||
$client_gateway_token->is_deleted = false;
|
||||
$client_gateway_token->token = '';
|
||||
$client_gateway_token->routing_number = '';
|
||||
|
||||
return $client_gateway_token;
|
||||
}
|
||||
}
|
437
app/Http/Controllers/ClientGatewayTokenController.php
Normal file
@ -0,0 +1,437 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Events\ClientGatewayToken\ClientGatewayTokenWasCreated;
|
||||
use App\Events\ClientGatewayToken\ClientGatewayTokenWasUpdated;
|
||||
use App\Factory\ClientGatewayTokenFactory;
|
||||
use App\Filters\ClientGatewayTokenFilters;
|
||||
use App\Http\Requests\ClientGatewayToken\CreateClientGatewayTokenRequest;
|
||||
use App\Http\Requests\ClientGatewayToken\DestroyClientGatewayTokenRequest;
|
||||
use App\Http\Requests\ClientGatewayToken\EditClientGatewayTokenRequest;
|
||||
use App\Http\Requests\ClientGatewayToken\ShowClientGatewayTokenRequest;
|
||||
use App\Http\Requests\ClientGatewayToken\StoreClientGatewayTokenRequest;
|
||||
use App\Http\Requests\ClientGatewayToken\UpdateClientGatewayTokenRequest;
|
||||
use App\Http\Requests\ClientGatewayToken\UploadClientGatewayTokenRequest;
|
||||
use App\Jobs\ClientGatewayToken\StoreClientGatewayToken;
|
||||
use App\Jobs\ClientGatewayToken\UpdateClientGatewayToken;
|
||||
use App\Models\Account;
|
||||
use App\Models\ClientGatewayToken;
|
||||
use App\Repositories\ClientGatewayTokenRepository;
|
||||
use App\Transformers\ClientGatewayTokenTransformer;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\BulkOptions;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use App\Utils\Traits\SavesDocuments;
|
||||
use App\Utils\Traits\Uploadable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
/**
|
||||
* Class ClientGatewayTokenController.
|
||||
* @covers App\Http\Controllers\ClientGatewayTokenController
|
||||
*/
|
||||
class ClientGatewayTokenController extends BaseController
|
||||
{
|
||||
use MakesHash;
|
||||
use Uploadable;
|
||||
use BulkOptions;
|
||||
use SavesDocuments;
|
||||
|
||||
protected $entity_type = ClientGatewayToken::class;
|
||||
|
||||
protected $entity_transformer = ClientGatewayTokenTransformer::class;
|
||||
|
||||
/**
|
||||
* @var ClientGatewayTokenRepository
|
||||
*/
|
||||
protected $client_gateway_token_gateway_token_repo;
|
||||
|
||||
/**
|
||||
* ClientGatewayTokenController constructor.
|
||||
* @param ClientGatewayTokenRepository $client_gateway_token_gateway_token_repo
|
||||
*/
|
||||
public function __construct(ClientGatewayTokenRepository $client_gateway_token_gateway_token_repo)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->client_gateway_token_repo = $client_gateway_token_gateway_token_repo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Get(
|
||||
* path="/api/v1/client_gateway_tokens",
|
||||
* operationId="getClientGatewayTokens",
|
||||
* tags={"client_gateway_tokens"},
|
||||
* summary="Gets a list of client_gateway_tokens",
|
||||
* description="Lists client_gateway_tokens, search and filters allow fine grained lists to be generated.
|
||||
|
||||
Query parameters can be added to performed more fine grained filtering of the client_gateway_tokens, these are handled by the ClientGatewayTokenFilters class which defines the methods available",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(ref="#/components/parameters/index"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="A list of client_gateway_tokens",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/ClientGatewayToken"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
* @param ClientGatewayTokenFilters $filters
|
||||
* @return Response|mixed
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$client_gateway_token_gateway_tokens = ClientGatewayToken::scope();
|
||||
|
||||
return $this->listResponse($client_gateway_token_gateway_tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param ShowClientGatewayTokenRequest $request
|
||||
* @param ClientGatewayToken $client_gateway_token
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/client_gateway_tokens/{id}",
|
||||
* operationId="showClientGatewayToken",
|
||||
* tags={"client_gateway_tokens"},
|
||||
* summary="Shows a client",
|
||||
* description="Displays a client by id",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The ClientGatewayToken Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the cl.ient object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/ClientGatewayToken"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function show(ShowClientGatewayTokenRequest $request, ClientGatewayToken $client_gateway_token)
|
||||
{
|
||||
return $this->itemResponse($client_gateway_token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param EditClientGatewayTokenRequest $request
|
||||
* @param ClientGatewayToken $client_gateway_token
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/client_gateway_tokens/{id}/edit",
|
||||
* operationId="editClientGatewayToken",
|
||||
* tags={"client_gateway_tokens"},
|
||||
* summary="Shows a client for editting",
|
||||
* description="Displays a client by id",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The ClientGatewayToken Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the client object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/ClientGatewayToken"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function edit(EditClientGatewayTokenRequest $request, ClientGatewayToken $client_gateway_token)
|
||||
{
|
||||
return $this->itemResponse($client_gateway_token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param UpdateClientGatewayTokenRequest $request
|
||||
* @param ClientGatewayToken $client_gateway_token
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Put(
|
||||
* path="/api/v1/client_gateway_tokens/{id}",
|
||||
* operationId="updateClientGatewayToken",
|
||||
* tags={"client_gateway_tokens"},
|
||||
* summary="Updates a client",
|
||||
* description="Handles the updating of a client by id",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The ClientGatewayToken Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the client object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/ClientGatewayToken"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function update(UpdateClientGatewayTokenRequest $request, ClientGatewayToken $client_gateway_token)
|
||||
{
|
||||
|
||||
$client_gateway_token = $this->client_gateway_token_repo->save($request->all(), $client_gateway_token);
|
||||
|
||||
return $this->itemResponse($client_gateway_token->fresh());
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param CreateClientGatewayTokenRequest $request
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/api/v1/client_gateway_tokens/create",
|
||||
* operationId="getClientGatewayTokensCreate",
|
||||
* tags={"client_gateway_tokens"},
|
||||
* summary="Gets a new blank client object",
|
||||
* description="Returns a blank object with default values",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="A blank client object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/ClientGatewayToken"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function create(CreateClientGatewayTokenRequest $request)
|
||||
{
|
||||
$client_gateway_token = ClientGatewayTokenFactory::create(auth()->user()->company()->id);
|
||||
|
||||
$client_gateway_token = $this->client_gateway_token_repo->save($request->all(), $client_gateway_token);
|
||||
|
||||
return $this->itemResponse($client_gateway_token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param StoreClientGatewayTokenRequest $request
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/client_gateway_tokens",
|
||||
* operationId="storeClientGatewayToken",
|
||||
* tags={"client_gateway_tokens"},
|
||||
* summary="Adds a client",
|
||||
* description="Adds an client to a company",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns the saved client object",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* @OA\JsonContent(ref="#/components/schemas/ClientGatewayToken"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function store(StoreClientGatewayTokenRequest $request)
|
||||
{
|
||||
$client_gateway_token = ClientGatewayTokenFactory::create(auth()->user()->company()->id);
|
||||
|
||||
$client_gateway_token = $this->client_gateway_token_repo->save($request->all(), $client_gateway_token);
|
||||
|
||||
return $this->itemResponse($client_gateway_token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param DestroyClientGatewayTokenRequest $request
|
||||
* @param ClientGatewayToken $client_gateway_token
|
||||
* @return Response
|
||||
*
|
||||
*
|
||||
* @throws \Exception
|
||||
* @OA\Delete(
|
||||
* path="/api/v1/client_gateway_tokens/{id}",
|
||||
* operationId="deleteClientGatewayToken",
|
||||
* tags={"client_gateway_tokens"},
|
||||
* summary="Deletes a client",
|
||||
* description="Handles the deletion of a client by id",
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Secret"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Api-Token"),
|
||||
* @OA\Parameter(ref="#/components/parameters/X-Requested-With"),
|
||||
* @OA\Parameter(ref="#/components/parameters/include"),
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="The ClientGatewayToken Hashed ID",
|
||||
* example="D2J234DFA",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* format="string",
|
||||
* ),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Returns a HTTP status",
|
||||
* @OA\Header(header="X-MINIMUM-CLIENT-VERSION", ref="#/components/headers/X-MINIMUM-CLIENT-VERSION"),
|
||||
* @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"),
|
||||
* @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"),
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=422,
|
||||
* description="Validation error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/ValidationError"),
|
||||
*
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="default",
|
||||
* description="Unexpected Error",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error"),
|
||||
* ),
|
||||
* )
|
||||
*/
|
||||
public function destroy(DestroyClientGatewayTokenRequest $request, ClientGatewayToken $client_gateway_token)
|
||||
{
|
||||
|
||||
$this->client_gateway_token_repo->delete($client_gateway_token);
|
||||
|
||||
return $this->itemResponse($client_gateway_token->fresh());
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -81,6 +81,7 @@ class LicenseController extends BaseController
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->checkLicense();
|
||||
|
||||
/* Catch claim license requests */
|
||||
if (config('ninja.environment') == 'selfhost' && request()->has('license_key')) {
|
||||
@ -140,4 +141,15 @@ class LicenseController extends BaseController
|
||||
|
||||
return response()->json($error, 400);
|
||||
}
|
||||
|
||||
private function checkLicense()
|
||||
{
|
||||
$account = auth()->user()->company()->account;
|
||||
|
||||
if($account->plan == 'white_label' && $account->plan_expires->lt(now())){
|
||||
$account->plan = null;
|
||||
$account->plan_expires = null;
|
||||
$account->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -165,6 +165,10 @@ class MigrationController extends BaseController
|
||||
{
|
||||
$company->clients()->forceDelete();
|
||||
$company->products()->forceDelete();
|
||||
$company->projects()->forceDelete();
|
||||
$company->tasks()->forceDelete();
|
||||
$company->vendors()->forceDelete();
|
||||
$company->expenses()->forceDelete();
|
||||
|
||||
$company->save();
|
||||
|
||||
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\ClientGatewayToken;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\ClientGatewayToken;
|
||||
|
||||
class CreateClientGatewayTokenRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->isAdmin();
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\ClientGatewayToken;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class DestroyClientGatewayTokenRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->isAdmin();
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\ClientGatewayToken;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class EditClientGatewayTokenRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->isAdmin();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\ClientGatewayToken;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class ShowClientGatewayTokenRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->isAdmin();
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\ClientGatewayToken;
|
||||
|
||||
use App\DataMapper\ClientSettings;
|
||||
use App\Http\Requests\Request;
|
||||
use App\Http\ValidationRules\Ninja\CanStoreClientsRule;
|
||||
use App\Http\ValidationRules\ValidClientGroupSettingsRule;
|
||||
use App\Models\Client;
|
||||
use App\Models\GroupSetting;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class StoreClientGatewayTokenRequest extends Request
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->isAdmin();
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
$rules = [
|
||||
'client_id' => 'required',
|
||||
'company_gateway_id' => 'required',
|
||||
'gateway_type_id' => 'required|integer',
|
||||
'meta' => 'required',
|
||||
];
|
||||
|
||||
|
||||
return $this->globalRules($rules);
|
||||
|
||||
}
|
||||
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
$input = $this->decodePrimaryKeys($input);
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\ClientGatewayToken;
|
||||
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\Http\Requests\Request;
|
||||
use App\Http\ValidationRules\ValidClientGroupSettingsRule;
|
||||
use App\Utils\Traits\ChecksEntityStatus;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdateClientGatewayTokenRequest extends Request
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return auth()->user()->isAdmin();
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
/* Ensure we have a client name, and that all emails are unique*/
|
||||
$rules = [];
|
||||
return $rules;
|
||||
}
|
||||
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
];
|
||||
}
|
||||
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
||||
}
|
@ -106,6 +106,10 @@ class Request extends FormRequest
|
||||
$input['project_id'] = $this->decodePrimaryKey($input['project_id']);
|
||||
}
|
||||
|
||||
if (array_key_exists('company_gateway_id', $input) && is_string($input['company_gateway_id'])) {
|
||||
$input['company_gateway_id'] = $this->decodePrimaryKey($input['company_gateway_id']);
|
||||
}
|
||||
|
||||
if (isset($input['client_contacts'])) {
|
||||
foreach ($input['client_contacts'] as $key => $contact) {
|
||||
if (! array_key_exists('send_email', $contact) || ! array_key_exists('id', $contact)) {
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace App\Jobs\Util;
|
||||
|
||||
use App\Models\Account;
|
||||
use App\Utils\Ninja;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
@ -40,5 +41,16 @@ class VersionCheck implements ShouldQueue
|
||||
if ($version_file) {
|
||||
Account::whereNotNull('id')->update(['latest_version' => $version_file]);
|
||||
}
|
||||
|
||||
if(Ninja::isSelfHost())
|
||||
{
|
||||
$account = Account::first();
|
||||
|
||||
if($account->plan == 'white_label' && $account->plan_expires->lt(now())){
|
||||
$account->plan = null;
|
||||
$account->plan_expires = null;
|
||||
$account->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,14 @@ class ClientGatewayToken extends BaseModel
|
||||
'hashed_id',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
'token',
|
||||
'routing_number',
|
||||
'gateway_customer_reference',
|
||||
'gateway_type_id',
|
||||
'meta',
|
||||
];
|
||||
|
||||
public function getEntityType()
|
||||
{
|
||||
return self::class;
|
||||
|
@ -397,7 +397,7 @@ class Invoice extends BaseModel
|
||||
$storage_path = Storage::$type($this->client->invoice_filepath().$this->numberFormatter().'.pdf');
|
||||
|
||||
if (! Storage::exists($this->client->invoice_filepath().$this->numberFormatter().'.pdf')) {
|
||||
event(new InvoiceWasUpdated($this, $this->company, Ninja::eventVars(auth()->user()->id)));
|
||||
event(new InvoiceWasUpdated($this, $this->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
CreateEntityPdf::dispatchNow($invitation);
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ class InvoiceInvitation extends BaseModel
|
||||
$storage_path = Storage::url($this->invoice->client->invoice_filepath().$this->invoice->numberFormatter().'.pdf');
|
||||
|
||||
if (! Storage::exists($this->invoice->client->invoice_filepath().$this->invoice->numberFormatter().'.pdf')) {
|
||||
event(new InvoiceWasUpdated($this->invoice, $this->company, Ninja::eventVars(auth()->user()->id)));
|
||||
event(new InvoiceWasUpdated($this->invoice, $this->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
CreateEntityPdf::dispatchNow($this);
|
||||
}
|
||||
|
||||
|
31
app/Repositories/ClientGatewayTokenRepository.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Repositories;
|
||||
|
||||
use App\Models\ClientGatewayToken;
|
||||
|
||||
/**
|
||||
* Class for ClientGatewayTokenRepository .
|
||||
*/
|
||||
class ClientGatewayTokenRepository extends BaseRepository
|
||||
{
|
||||
|
||||
public function save(array $data, ClientGatewayToken $client_gateway_token) :ClientGatewayToken
|
||||
{
|
||||
|
||||
$client_gateway_token->fill($data);
|
||||
$client_gateway_token->save();
|
||||
|
||||
return $client_gateway_token->fresh();
|
||||
}
|
||||
|
||||
}
|
@ -144,11 +144,11 @@ class ApplyPayment
|
||||
->ledger()
|
||||
->updateCreditBalance(($this->amount_applied * -1), "Credit payment applied to Invoice {$this->invoice->number}");
|
||||
|
||||
event(new InvoiceWasUpdated($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user()->id)));
|
||||
event(new InvoiceWasUpdated($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
|
||||
if ((int)$this->invoice->balance == 0) {
|
||||
$this->invoice->service()->deletePdf();
|
||||
event(new InvoiceWasPaid($this->invoice, $this->payment, $this->payment->company, Ninja::eventVars(auth()->user()->id)));
|
||||
event(new InvoiceWasPaid($this->invoice, $this->payment, $this->payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ class UpdateInvoicePayment
|
||||
|
||||
InvoiceWorkflowSettings::dispatchNow($invoice);
|
||||
|
||||
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars()));
|
||||
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
});
|
||||
|
||||
$this->payment->save();
|
||||
|
@ -14,8 +14,8 @@ return [
|
||||
'require_https' => env('REQUIRE_HTTPS', true),
|
||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||
'app_domain' => env('APP_DOMAIN', ''),
|
||||
'app_version' => '5.1.48',
|
||||
'app_tag' => '5.1.48-release',
|
||||
'app_version' => '5.1.49',
|
||||
'app_tag' => '5.1.49-release',
|
||||
'minimum_client_version' => '5.0.16',
|
||||
'terms_version' => '1.0.1',
|
||||
'api_secret' => env('API_SECRET', false),
|
||||
|
BIN
public/images/welcome/circle-2.png
Normal file
After Width: | Height: | Size: 101 B |
BIN
public/images/welcome/compScreen.png
Normal file
After Width: | Height: | Size: 164 KiB |
BIN
public/images/welcome/create-icon.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
public/images/welcome/email.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
public/images/welcome/forum.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
public/images/welcome/integrate-icon.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
public/images/welcome/logo.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
public/images/welcome/question.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
public/images/welcome/slack.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
public/images/welcome/upload-icon.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
@ -37,6 +37,8 @@ Route::group(['middleware' => ['api_db', 'token_auth', 'locale'], 'prefix' => 'a
|
||||
Route::put('clients/{client}/upload', 'ClientController@upload')->name('clients.upload');
|
||||
Route::post('clients/bulk', 'ClientController@bulk')->name('clients.bulk');
|
||||
|
||||
Route::resource('client_gateway_tokens', 'ClientGatewayTokenController');
|
||||
|
||||
Route::post('connected_account', 'ConnectedAccountController@index');
|
||||
Route::post('connected_account/gmail', 'ConnectedAccountController@handleGmailOauth');
|
||||
|
||||
|
181
tests/Feature/ClientGatewayTokenApiTest.php
Normal file
@ -0,0 +1,181 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\CompanyGateway;
|
||||
use App\Models\GatewayType;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Tests\MockAccountData;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @covers App\Http\Controllers\ClientGatewayTokenController
|
||||
*/
|
||||
class ClientGatewayTokenApiTest extends TestCase
|
||||
{
|
||||
use MakesHash;
|
||||
use DatabaseTransactions;
|
||||
use MockAccountData;
|
||||
|
||||
public function setUp() :void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->withoutMiddleware(
|
||||
ThrottleRequests::class
|
||||
);
|
||||
|
||||
if (! config('ninja.testvars.stripe')) {
|
||||
$this->markTestSkipped('Skip test no company gateways installed');
|
||||
}
|
||||
|
||||
$this->faker = \Faker\Factory::create();
|
||||
|
||||
Model::reguard();
|
||||
|
||||
$this->makeTestData();
|
||||
|
||||
$this->withoutExceptionHandling();
|
||||
|
||||
CompanyGateway::whereNotNull('id')->delete();
|
||||
|
||||
$data = [];
|
||||
$data[1]['min_limit'] = -1;
|
||||
$data[1]['max_limit'] = -1;
|
||||
$data[1]['fee_amount'] = 0.00;
|
||||
$data[1]['fee_percent'] = 2;
|
||||
$data[1]['fee_tax_name1'] = 'GST';
|
||||
$data[1]['fee_tax_rate1'] = 10;
|
||||
$data[1]['fee_tax_name2'] = 'GST';
|
||||
$data[1]['fee_tax_rate2'] = 10;
|
||||
$data[1]['fee_tax_name3'] = 'GST';
|
||||
$data[1]['fee_tax_rate3'] = 10;
|
||||
$data[1]['adjust_fee_percent'] = true;
|
||||
$data[1]['fee_cap'] = 0;
|
||||
$data[1]['is_enabled'] = true;
|
||||
|
||||
$data[2]['min_limit'] = -1;
|
||||
$data[2]['max_limit'] = -1;
|
||||
$data[2]['fee_amount'] = 0.00;
|
||||
$data[2]['fee_percent'] = 1;
|
||||
$data[2]['fee_tax_name1'] = 'GST';
|
||||
$data[2]['fee_tax_rate1'] = 10;
|
||||
$data[2]['fee_tax_name2'] = 'GST';
|
||||
$data[2]['fee_tax_rate2'] = 10;
|
||||
$data[2]['fee_tax_name3'] = 'GST';
|
||||
$data[2]['fee_tax_rate3'] = 10;
|
||||
$data[2]['adjust_fee_percent'] = true;
|
||||
$data[2]['fee_cap'] = 0;
|
||||
$data[2]['is_enabled'] = true;
|
||||
|
||||
//disable ach here
|
||||
$json_config = json_decode(config('ninja.testvars.stripe'));
|
||||
|
||||
$this->cg = new CompanyGateway;
|
||||
$this->cg->company_id = $this->company->id;
|
||||
$this->cg->user_id = $this->user->id;
|
||||
$this->cg->gateway_key = 'd14dd26a37cecc30fdd65700bfb55b23';
|
||||
$this->cg->require_cvv = true;
|
||||
$this->cg->require_billing_address = true;
|
||||
$this->cg->require_shipping_address = true;
|
||||
$this->cg->update_details = true;
|
||||
$this->cg->config = encrypt(json_encode($json_config));
|
||||
$this->cg->fees_and_limits = $data;
|
||||
$this->cg->save();
|
||||
}
|
||||
|
||||
public function testClientGatewayPostPost()
|
||||
{
|
||||
$data = [
|
||||
'client_id' => $this->client->hashed_id,
|
||||
'company_gateway_id' => $this->cg->hashed_id,
|
||||
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
||||
'meta' => '{}',
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/client_gateway_tokens', $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertNotNull($arr['data']['token']);
|
||||
|
||||
}
|
||||
|
||||
public function testClientPut()
|
||||
{
|
||||
|
||||
|
||||
$data = [
|
||||
'client_id' => $this->client->hashed_id,
|
||||
'company_gateway_id' => $this->cg->hashed_id,
|
||||
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
||||
'meta' => '{}',
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/client_gateway_tokens', $data);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$data = [
|
||||
'token' => 'a_testy_token',
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->put('/api/v1/client_gateway_tokens/'.$arr['data']['id'], $data);
|
||||
|
||||
$response->assertStatus(200);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$this->assertEquals('a_testy_token', $arr['data']['token']);
|
||||
}
|
||||
|
||||
public function testClientGet()
|
||||
{
|
||||
|
||||
$data = [
|
||||
'client_id' => $this->client->hashed_id,
|
||||
'company_gateway_id' => $this->cg->hashed_id,
|
||||
'gateway_type_id' => GatewayType::CREDIT_CARD,
|
||||
'meta' => '{}',
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->post('/api/v1/client_gateway_tokens', $data);
|
||||
|
||||
$arr = $response->json();
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $this->token,
|
||||
])->get('/api/v1/client_gateway_tokens/'.$arr['data']['id']);
|
||||
|
||||
$response->assertStatus(200);
|
||||
}
|
||||
|
||||
}
|