This commit is contained in:
Andras Bacsai 2023-07-13 15:07:42 +02:00
parent 5bda8a426c
commit f3f8a62a18
14 changed files with 206 additions and 3 deletions

View File

@ -21,7 +21,7 @@ class Kernel extends HttpKernel
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class, \App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
// \App\Http\Middleware\LicenseValid::class, \App\Http\Middleware\LicenseValid::class,
]; ];
/** /**

View File

@ -16,7 +16,10 @@ class LicenseValid
*/ */
public function handle(Request $request, Closure $next): Response public function handle(Request $request, Closure $next): Response
{ {
if (!config('coolify.self_hosted')) { if (isCloud()) {
if (isDev()) {
return $next($request);
}
$value = Cache::get('license_key'); $value = Cache::get('license_key');
if (!$value) { if (!$value) {
ray($request->path()); ray($request->path());

View File

@ -0,0 +1,15 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Subscription extends Model
{
protected $guarded = [];
public function team()
{
return $this->belongsTo(Team::class);
}
}

View File

@ -66,7 +66,10 @@ public function routeNotificationForEmail(string $attribute = 'recipients')
} }
public function subscription()
{
return $this->hasOne(Subscription::class);
}
public function projects() public function projects()
{ {
return $this->hasMany(Project::class); return $this->hasMany(Project::class);

11
app/Models/Webhook.php Normal file
View File

@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Webhook extends Model
{
protected $guarded = [];
}

View File

@ -4,6 +4,7 @@
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\URL;
use Visus\Cuid2\Cuid2; use Visus\Cuid2\Cuid2;
use Illuminate\Support\Str; use Illuminate\Support\Str;
@ -127,3 +128,26 @@ function isDev()
{ {
return config('app.env') === 'local'; return config('app.env') === 'local';
} }
function isCloud()
{
return !config('coolify.self_hosted');
}
function getSubscriptionLink()
{
$user_id = auth()->user()->id;
$email = auth()->user()->email ?? null;
$name = auth()->user()->name ?? null;
$url = "https://store.coollabs.io/checkout/buy/d0b28c6a-9b57-40bf-8b84-89fbafde6526?";
if ($user_id) {
$url .= "checkout[custom][user_id]={$user_id}";
}
if ($email) {
$url .= "?checkout[email]={$email}";
}
if ($name) {
$url .= "&checkout[name]={$name}";
}
$url = "?checkout[custom][user_id]={$user_id}&checkout[email]={$email}&checkout[name]={$name}";
ray($url);
return $url;
}

View File

@ -2,6 +2,8 @@
return [ return [
'self_hosted' => env('SELF_HOSTED', true), 'self_hosted' => env('SELF_HOSTED', true),
'lemon_squeezy_webhook_secret' => env('LEMON_SQUEEZY_WEBHOOK_SECRET'),
'lemon_squeezy_product_id' => env('LEMON_SQUEEZY_PRODUCT_ID'),
'mux_enabled' => env('MUX_ENABLED', true), 'mux_enabled' => env('MUX_ENABLED', true),
'dev_webhook' => env('SERVEO_URL'), 'dev_webhook' => env('SERVEO_URL'),
'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'), 'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'),

View File

@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('subscriptions', function (Blueprint $table) {
$table->id();
$table->string('lemon_order_id');
$table->string('lemon_product_id');
$table->string('lemon_variant_id');
$table->string('lemon_customer_id');
$table->string('lemon_status');
$table->string('lemon_trial_ends_at');
$table->string('lemon_renews_at');
$table->string('lemon_ends_at');
$table->string('lemon_update_payment_menthod_url');
$table->foreignId('team_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('subscriptions');
}
};

View File

@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('webhooks', function (Blueprint $table) {
$table->id();
$table->enum('status', ['pending', 'success', 'failed'])->default('pending');
$table->enum('type', ['github', 'gitlab', 'bitbucket', 'lemonsqueezy']);
$table->longText('payload');
$table->longText('failure_reason')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('webhooks');
}
};

View File

@ -0,0 +1,17 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class SubscriptionSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class WebhookSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
//
}
}

View File

@ -22,6 +22,7 @@
} }
</style> </style>
@livewireStyles @livewireStyles
<script src="https://app.lemonsqueezy.com/js/lemon.js" defer></script>
</head> </head>
<body> <body>

View File

@ -18,4 +18,6 @@
<div class="stat-desc">Applications, databases, etc...</div> <div class="stat-desc">Applications, databases, etc...</div>
</div> </div>
</div> </div>
{{-- <a href="{{ getSubscriptionLink() }}">Subscribe</a> --}}
</x-layout> </x-layout>

View File

@ -4,6 +4,7 @@
use App\Models\ApplicationPreview; use App\Models\ApplicationPreview;
use App\Models\PrivateKey; use App\Models\PrivateKey;
use App\Models\GithubApp; use App\Models\GithubApp;
use App\Models\Webhook;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str; use Illuminate\Support\Str;
@ -170,3 +171,42 @@
return general_error_handler(err: $e); return general_error_handler(err: $e);
} }
}); });
Route::post('/subscriptions/events', function () {
try {
$secret = config('coolify.lemon_squeezy_webhook_secret');
$payload = request()->collect();
$hash = hash_hmac('sha256', $payload, $secret);
$signature = '';
if (!hash_equals($hash, $signature)) {
return response('Invalid signature.', 400);
}
$webhook = Webhook::create([
'type' => 'lemonsqueezy',
'payload' => $payload
]);
$event = data_get($payload, 'meta.event_name');
$email = data_get($payload, 'data.attributes.user_email');
$update_payment_method = data_get($payload, 'data.attributes.urls.update_payment_method');
switch ($event) {
case 'subscription_created':
break;
}
ray($payload);
$webhook->update([
'status' => 'success',
]);
} catch (\Exception $e) {
$webhook->update([
'status' => 'failed',
'failure_reason' => $e->getMessage()
]);
} finally {
return response('OK');
}
});