diff --git a/app/Http/Controllers/TeamQuotasController.php b/app/Http/Controllers/TeamQuotasController.php index 0099080..cf5b05b 100644 --- a/app/Http/Controllers/TeamQuotasController.php +++ b/app/Http/Controllers/TeamQuotasController.php @@ -19,6 +19,7 @@ public function index(Team $team) 'currentUsage' => $quota->currentUsage(), 'maxUsage' => $quota->maxUsage, 'isSoftQuota' => $quota->isSoftQuota, + 'resetPeriod' => $quota->resetPeriod, 'almostQuotaReached' => $quota->almostQuotaReached(), 'isIntrinsic' => $key === 'swarms', // Mark swarms as intrinsic ]; diff --git a/app/Models/PricingPlan/ItemQuota.php b/app/Models/PricingPlan/ItemQuota.php index 4ea9197..5a2e129 100644 --- a/app/Models/PricingPlan/ItemQuota.php +++ b/app/Models/PricingPlan/ItemQuota.php @@ -11,7 +11,8 @@ public function __construct( public string $name, public int $maxUsage, protected Closure $getCurrentUsage, - public bool $isSoftQuota = false + public bool $isSoftQuota = false, + public ?string $resetPeriod = null ) {} public function ensureQuota(): void diff --git a/app/Models/Team.php b/app/Models/Team.php index f35ee8f..fc78681 100644 --- a/app/Models/Team.php +++ b/app/Models/Team.php @@ -186,25 +186,29 @@ public function quotas(): UsageQuotas name: 'Nodes', maxUsage: max($plan->quotas['nodes']['limit'], $override->nodes), getCurrentUsage: fn () => $this->nodes()->count(), - isSoftQuota: $plan->quotas['nodes']['soft'] + isSoftQuota: $plan->quotas['nodes']['soft'], + resetPeriod: $plan->quotas['nodes']['reset_period'] ), new ItemQuota( name: 'Swarms', maxUsage: max($plan->quotas['swarms']['limit'], $override->swarms), getCurrentUsage: fn () => $this->swarms()->count(), - isSoftQuota: $plan->quotas['swarms']['soft'] + isSoftQuota: $plan->quotas['swarms']['soft'], + resetPeriod: $plan->quotas['swarms']['reset_period'] ), new ItemQuota( name: 'Services', maxUsage: max($plan->quotas['services']['limit'], $override->services), getCurrentUsage: fn () => $this->services()->count(), - isSoftQuota: $plan->quotas['services']['soft'] + isSoftQuota: $plan->quotas['services']['soft'], + resetPeriod: $plan->quotas['services']['reset_period'] ), new ItemQuota( name: 'Deployments', maxUsage: max($plan->quotas['deployments']['limit'], $override->deployments), - getCurrentUsage: fn () => $this->deployments()->count(), - isSoftQuota: $plan->quotas['deployments']['soft'] + getCurrentUsage: fn () => $this->deployments()->where('created_at', '>=', now()->startOfDay())->count(), + isSoftQuota: $plan->quotas['deployments']['soft'], + resetPeriod: $plan->quotas['deployments']['reset_period'] ) ); } diff --git a/config/billing.php b/config/billing.php index ff53394..cee84ca 100644 --- a/config/billing.php +++ b/config/billing.php @@ -11,12 +11,12 @@ 'description' => 'Perfect plan to try the service or host non-critical applications', 'product_id' => env('PADDLE_PLAN_HOBBY_PRODUCT_ID'), 'price_id' => env('PADDLE_PLAN_HOBBY_PRICE_ID'), - 'billing_cycle' => 'yearly', // Added billing cycle + 'billing_cycle' => 'yearly', 'quotas' => [ - 'nodes' => ['limit' => 1, 'soft' => false], - 'swarms' => ['limit' => 1, 'soft' => false], - 'services' => ['limit' => 20, 'soft' => true], - 'deployments' => ['limit' => 100, 'soft' => true], + 'nodes' => ['limit' => 1, 'soft' => false, 'reset_period' => null], + 'swarms' => ['limit' => 1, 'soft' => false, 'reset_period' => null], + 'services' => ['limit' => 20, 'soft' => true, 'reset_period' => null], + 'deployments' => ['limit' => 100, 'soft' => true, 'reset_period' => 'daily'], ], ], [ @@ -25,12 +25,12 @@ 'description' => 'Need more power or an additional features? This is your choice!', 'product_id' => env('PADDLE_PLAN_STARTUP_PRODUCT_ID'), 'price_id' => env('PADDLE_PLAN_STARTUP_PRICE_ID'), - 'billing_cycle' => 'monthly', // Added billing cycle + 'billing_cycle' => 'monthly', 'quotas' => [ - 'nodes' => ['limit' => 5, 'soft' => true], - 'swarms' => ['limit' => 1, 'soft' => false], - 'services' => ['limit' => 10, 'soft' => true], - 'deployments' => ['limit' => 100, 'soft' => true], + 'nodes' => ['limit' => 5, 'soft' => true, 'reset_period' => null], + 'swarms' => ['limit' => 1, 'soft' => false, 'reset_period' => null], + 'services' => ['limit' => 10, 'soft' => true, 'reset_period' => null], + 'deployments' => ['limit' => 100, 'soft' => true, 'reset_period' => 'daily'], ], ], ], @@ -41,10 +41,10 @@ 'product_id' => null, 'price_id' => null, 'quotas' => [ - 'nodes' => ['limit' => 1, 'soft' => false], - 'swarms' => ['limit' => 1, 'soft' => false], - 'services' => ['limit' => 3, 'soft' => false], - 'deployments' => ['limit' => 20, 'soft' => false], + 'nodes' => ['limit' => 1, 'soft' => false, 'reset_period' => null], + 'swarms' => ['limit' => 1, 'soft' => false, 'reset_period' => null], + 'services' => ['limit' => 3, 'soft' => false, 'reset_period' => null], + 'deployments' => ['limit' => 20, 'soft' => false, 'reset_period' => 'daily'], ], ], 'selfHostedPlan' => [ @@ -54,10 +54,10 @@ 'product_id' => null, 'price_id' => null, 'quotas' => [ - 'nodes' => ['limit' => 1000, 'soft' => true], - 'swarms' => ['limit' => 1, 'soft' => false], - 'services' => ['limit' => 5000, 'soft' => true], - 'deployments' => ['limit' => 100000, 'soft' => true], + 'nodes' => ['limit' => 1000, 'soft' => true, 'reset_period' => null], + 'swarms' => ['limit' => 1, 'soft' => false, 'reset_period' => null], + 'services' => ['limit' => 5000, 'soft' => true, 'reset_period' => null], + 'deployments' => ['limit' => 100000, 'soft' => true, 'reset_period' => 'daily'], ], ], ], diff --git a/database/migrations/2024_09_23_190601_alter_teams_change_quotas_override_to_jsonb.php b/database/migrations/2024_09_23_190601_alter_teams_change_quotas_override_to_jsonb.php new file mode 100644 index 0000000..b2f6135 --- /dev/null +++ b/database/migrations/2024_09_23_190601_alter_teams_change_quotas_override_to_jsonb.php @@ -0,0 +1,34 @@ +jsonb('quotas_override')->default(json_encode([ + 'nodes' => 0, + 'swarms' => 0, + 'services' => 0, + 'deployments' => 0, + ]))->change(); + }); + } + + public function down(): void + { + Schema::table('teams', function (Blueprint $table) { + // Revert the column type back to json + $table->json('quotas_override')->default(json_encode([ + 'nodes' => 0, + 'swarms' => 0, + 'services' => 0, + 'deployments' => 0, + ]))->change(); + }); + } +}; diff --git a/resources/js/Pages/Nodes/Partials/DockerRegistries.vue b/resources/js/Pages/Nodes/Partials/DockerRegistries.vue index fb64696..7152553 100644 --- a/resources/js/Pages/Nodes/Partials/DockerRegistries.vue +++ b/resources/js/Pages/Nodes/Partials/DockerRegistries.vue @@ -16,7 +16,10 @@ const props = defineProps({ const { encrypt } = useCrypto(); const form = useForm({ - registries: props.swarm.data.registries, + registries: props.swarm.data.registries.map((registry) => ({ + ...registry, + password: null, + })), }); const makeId = (prefix) => prefix + "-" + Math.random().toString(36).slice(2); diff --git a/resources/js/Pages/Nodes/Partials/S3Storages.vue b/resources/js/Pages/Nodes/Partials/S3Storages.vue index f8dbd5b..b4c2daa 100644 --- a/resources/js/Pages/Nodes/Partials/S3Storages.vue +++ b/resources/js/Pages/Nodes/Partials/S3Storages.vue @@ -17,7 +17,10 @@ const props = defineProps({ const { encrypt } = useCrypto(); const form = useForm({ - s3Storages: props.swarm.data.s3Storages, + s3Storages: props.swarm.data.s3Storages.map((storage) => ({ + ...storage, + secretKey: null, + })), }); const addStorage = () => { diff --git a/resources/js/Pages/Teams/Quotas.vue b/resources/js/Pages/Teams/Quotas.vue index 4051ff4..24d8739 100644 --- a/resources/js/Pages/Teams/Quotas.vue +++ b/resources/js/Pages/Teams/Quotas.vue @@ -46,8 +46,12 @@ const quotaDescriptions = { swarms: "The maximum number of swarms you can create for your team.", services: "The maximum number of services you can deploy across all swarms.", - deployments: "The maximum number of deployments you can perform.", + deployments: "The maximum number of deployments you can perform per day.", }; + +function getResetPeriodText(quota: ItemQuota): string | null { + return quota.resetPeriod === "daily" ? "Resets daily" : null; +}