1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 00:11:35 +02:00

Add ability to purge clients

This commit is contained in:
David Bomba 2022-01-30 10:46:39 +11:00
parent 4a88491195
commit 263bcd8126
14 changed files with 489 additions and 250 deletions

View File

@ -510,7 +510,7 @@ class ClientController extends BaseController
$ids = request()->input('ids');
$clients = Client::withTrashed()->whereIn('id', $this->transformKeys($ids))->cursor();
if(!in_array($action, ['restore','archive','delete']))
if(!in_array($action, ['restore','archive','delete','purge']))
return response()->json(['message' => 'That action is not available.'], 400);
$clients->each(function ($client, $key) use ($action) {

View File

@ -0,0 +1,107 @@
<?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://www.elastic.co/licensing/elastic-license
*/
namespace App\Http\Controllers\InAppPurchase;
use App\Http\Controllers\BaseController;
use Illuminate\Http\Request;
/**
* Class AppleController.
*/
class AppleController extends BaseController
{
public function __construct()
{
}
/**
* Process Apple Purchase Confirmation Webhook.
*
*
* @OA\Post(
* path="/api/v1/apple/confirm_purchase",
* operationId="confirmApplePurchase",
* tags={"postmark"},
* summary="Processing webhooks from Apple for in app purchases",
* description="Adds an credit to the system",
* @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 credit 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\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 confirm_purchase(Request $request)
{
//store transaction_id in accounts table for future reference.
}
/**
* Process Apple Purchase Confirmation Webhook.
*
*
* @OA\Post(
* path="/api/v1/apple/process_webhook",
* operationId="processAppleWebhook",
* tags={"postmark"},
* summary="Processing event webhooks from Apple for in purchase / subscription status update",
* description="Adds an credit to the system",
* @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 credit 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\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 process_webhook(Request $request)
{
}
}

View File

@ -14,9 +14,8 @@ namespace App\Http\Middleware;
use App\DataMapper\Analytics\DbQuery;
use App\Utils\Ninja;
use Closure;
use DB;
use Illuminate\Http\Request;
use Log;
use Illuminate\Support\Facades\DB;
use Turbo124\Beacon\Facades\LightLogs;
/**
@ -61,7 +60,9 @@ class QueryLogging
$ip = '';
if(request()->header('Cf-Connecting-Ip'))
if(request()->hasHeader('Cf-Connecting-Ip'))
$ip = request()->header('Cf-Connecting-Ip');
elseif(request()->hasHeader('X-Forwarded-For'))
$ip = request()->header('Cf-Connecting-Ip');
else{
$ip = request()->ip();

View File

@ -140,7 +140,15 @@ class CreateAccount
->increment()
->queue();
$ip = request()->hasHeader('Cf-Connecting-Ip') ? request()->header('Cf-Connecting-Ip') : request()->getClientIp();
$ip = '';
if(request()->hasHeader('Cf-Connecting-Ip'))
$ip = request()->header('Cf-Connecting-Ip');
elseif(request()->hasHeader('X-Forwarded-For'))
$ip = request()->header('Cf-Connecting-Ip');
else
$ip = request()->ip();
$platform = request()->has('platform') ? request()->input('platform') : 'www';
LightLogs::create(new AccountPlatform($platform, request()->server('HTTP_USER_AGENT'), $ip))

View File

@ -0,0 +1,79 @@
<?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://www.elastic.co/licensing/elastic-license
*/
namespace App\Libraries\InApp\StoreKit;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
/**
* Class Apple.
*/
class Apple
{
private string $bundle_id = '';
private string $issuer_id = '';
private string $key_id = '';
private string $private_key = '';
private string $alg = 'ES256';
public function createJwt()
{
$this->bundle_id = config('ninja.ninja_apple_bundle_id');
$this->issuer_id = config('ninja.ninja_apple_issuer_id');
$this->key_id = config('ninja.ninja_apple_api_key');
$this->private_key = config('ninja.ninja_apple_private_key');
$issue_time = time();
$expiration_time = $issue_time + 60 * 60;
$header = [
'alg' => $this->alg,
'kid' => $this->key_id,
'typ' => 'JWT'
];
$payload = [
'iss'=> $this->issuer_id,
'iat'=> $issue_time,
'exp'=> $expiration_time,
'aud'=> 'appstoreconnect-v1',
'nonce'=> $this->guidv4(),
'bid'=> $this->bundle_id
];
$jwt = JWT::encode($payload, $this->private_key, $this->alg, $header);
$decoded = JWT::decode($jwt, new Key($this->private_key, $this->alg));
return $decoded;
}
private function guidv4()
{
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex(random_bytes(16)), 4));
}
}

View File

@ -245,6 +245,11 @@ class Client extends BaseModel implements HasLocalePreference
return $this->hasMany(RecurringInvoice::class)->withTrashed();
}
public function recurring_expenses()
{
return $this->hasMany(RecurringExpense::class)->withTrashed();
}
public function shipping_country()
{
return $this->belongsTo(Country::class, 'shipping_country_id', 'id');

View File

@ -92,4 +92,26 @@ class ClientRepository extends BaseRepository
ClientFactory::create(auth()->user()->company()->id, auth()->user()->id)
);
}
public function purge($client)
{
$client->contacts()->forceDelete();
$client->tasks()->forceDelete();
$client->invoices()->forceDelete();
$client->ledger()->forceDelete();
$client->gateway_tokens()->forceDelete();
$client->projects()->forceDelete();
$client->credits()->forceDelete();
$client->quotes()->forceDelete();
$client->activities()->forceDelete();
$client->recurring_invoices()->forceDelete();
$client->expenses()->forceDelete();
$client->recurring_expenses()->forceDelete();
$client->system_logs()->forceDelete();
$client->documents()->forceDelete();
$client->payments()->forceDelete();
$client->forceDelete();
}
}

View File

@ -114,10 +114,14 @@ class Ninja
public static function eventVars($user_id = null)
{
if(request()->hasHeader('Cf-Connecting-Ip'))
$ip = request()->header('Cf-Connecting-Ip');
else
$ip = request()->getClientIp();
$ip = '';
if(request()->hasHeader('Cf-Connecting-Ip'))
$ip = request()->header('Cf-Connecting-Ip');
elseif(request()->hasHeader('X-Forwarded-For'))
$ip = request()->header('Cf-Connecting-Ip');
else
$ip = request()->ip();
return [
'ip' => $ip,

View File

@ -44,6 +44,7 @@
"eway/eway-rapid-php": "^1.3",
"fakerphp/faker": "^1.14",
"fideloper/proxy": "^4.2",
"firebase/php-jwt": "^5",
"fruitcake/laravel-cors": "^2.0",
"gocardless/gocardless-pro": "^4.12",
"google/apiclient": "^2.7",

462
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -59,13 +59,6 @@ return [
'default' => env('DB_CONNECTION', 'mysql'),
],
// 'db_options' => [
// PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => false,
// PDO::MYSQL_ATTR_SSL_KEY => env("DB_CLIENT_KEY", ''),
// PDO::MYSQL_ATTR_SSL_CERT => env("DB_CLIENT_CERT", ''),
// PDO::MYSQL_ATTR_SSL_CA => env("DB_CA_CERT", ''),
// ],
'i18n' => [
'timezone_id' => env('DEFAULT_TIMEZONE', 1),
'country_id' => env('DEFAULT_COUNTRY', 840), // United Stated
@ -187,4 +180,10 @@ return [
'ninja_default_company_gateway_id' => env('NINJA_COMPANY_GATEWAY_ID', null),
'ninja_hosted_secret' => env('NINJA_HOSTED_SECRET', null),
'internal_queue_enabled' => env('INTERNAL_QUEUE_ENABLED', true),
'ninja_apple_api_key' => env('APPLE_API_KEY', false),
'ninja_apple_private_key' => env('APPLE_PRIVATE_KEY', false),
'ninja_apple_bundle_id' => env('APPLE_BUNDLE_ID', false),
'ninja_apple_issuer_id' => env('APPLE_ISSUER_ID', false)
];

View File

@ -1,5 +1,6 @@
<?php
use App\Models\Country;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
@ -16,7 +17,15 @@ class AddClientCountToAccountsTable extends Migration
Schema::table('accounts', function (Blueprint $table) {
$table->unsignedInteger('hosted_client_count')->nullable();
$table->unsignedInteger('hosted_company_count')->nullable();
$table->string('inapp_transaction_id', 100)->nullable();
});
$country = Country::find(250);
if($country){
$country->thousand_separator = " ";
$country->save();
}
}
/**

View File

@ -104,6 +104,7 @@ class CountriesSeeder extends Seeder
'FR' => [ // France
'swap_postal_code' => true,
'swap_currency_symbol' => true,
'thousand_separator' => ' ',
],
'GR' => [ // Greece
'swap_currency_symbol' => true,

View File

@ -226,8 +226,9 @@ Route::match(['get', 'post'], 'payment_notification_webhook/{company_key}/{compa
Route::post('api/v1/postmark_webhook', 'PostMarkController@webhook')->middleware('throttle:1000,1');
Route::get('token_hash_router', 'OneTimeTokenController@router')->middleware('throttle:100,1');
Route::get('webcron', 'WebCronController@index')->middleware('throttle:100,1');;
Route::post('api/v1/get_migration_account', 'HostedMigrationController@getAccount')->middleware('guest')->middleware('throttle:100,1');;
Route::post('api/v1/confirm_forwarding', 'HostedMigrationController@confirmForwarding')->middleware('guest')->middleware('throttle:100,1');;
Route::get('webcron', 'WebCronController@index')->middleware('throttle:100,1');
Route::post('api/v1/get_migration_account', 'HostedMigrationController@getAccount')->middleware('guest')->middleware('throttle:100,1');
Route::post('api/v1/confirm_forwarding', 'HostedMigrationController@confirmForwarding')->middleware('guest')->middleware('throttle:100,1');
Route::post('api/v1/process_webhook', 'InAppPurchase\AppleController@process_webhook')->middleware('throttle:1000,1');
Route::post('api/v1/confirm_purchase', 'InAppPurchase\AppleController@confirm_purchase')->middleware('throttle:1000,1');
Route::fallback('BaseController@notFound');