diff --git a/app/Http/Middleware/DecideWhatToDoWithUser.php b/app/Http/Middleware/DecideWhatToDoWithUser.php index 30780910b..f4adaaa9b 100644 --- a/app/Http/Middleware/DecideWhatToDoWithUser.php +++ b/app/Http/Middleware/DecideWhatToDoWithUser.php @@ -44,7 +44,7 @@ class DecideWhatToDoWithUser if (auth()->user()->hasVerifiedEmail() && $request->path() === 'verify') { return redirect(RouteServiceProvider::HOME); } - if (isSubscriptionActive() && $request->path() === 'subscription') { + if (isSubscriptionActive() && $request->routeIs('subscription.index')) { return redirect(RouteServiceProvider::HOME); } return $next($request); diff --git a/app/Livewire/Subscription/Actions.php b/app/Livewire/Subscription/Actions.php index bd4dbd69a..3050e38ab 100644 --- a/app/Livewire/Subscription/Actions.php +++ b/app/Livewire/Subscription/Actions.php @@ -7,6 +7,13 @@ use Livewire\Component; class Actions extends Component { + public $server_limits = 0; + public function mount() + { + $limits = currentTeam()->limits; + $this->server_limits = data_get($limits, 'serverLimit', 0); + + } public function cancel() { try { @@ -69,7 +76,8 @@ class Actions extends Component return handleError($e, $this); } } - public function stripeCustomerPortal() { + public function stripeCustomerPortal() + { $session = getStripeCustomerPortalSession(currentTeam()); redirect($session->url); } diff --git a/app/Livewire/Subscription/Index.php b/app/Livewire/Subscription/Index.php index afc3729c6..4f36750c7 100644 --- a/app/Livewire/Subscription/Index.php +++ b/app/Livewire/Subscription/Index.php @@ -10,14 +10,19 @@ class Index extends Component { public InstanceSettings $settings; public bool $alreadySubscribed = false; - public function mount() { + public function mount() + { if (!isCloud()) { return redirect(RouteServiceProvider::HOME); } + if (data_get(currentTeam(), 'subscription')) { + return redirect()->route('subscription.show'); + } $this->settings = InstanceSettings::get(); $this->alreadySubscribed = currentTeam()->subscription()->exists(); } - public function stripeCustomerPortal() { + public function stripeCustomerPortal() + { $session = getStripeCustomerPortalSession(currentTeam()); if (is_null($session)) { return; diff --git a/app/Livewire/Subscription/Show.php b/app/Livewire/Subscription/Show.php new file mode 100644 index 000000000..ad677ce53 --- /dev/null +++ b/app/Livewire/Subscription/Show.php @@ -0,0 +1,22 @@ +route('dashboard'); + } + if (!data_get(currentTeam(), 'subscription')) { + return redirect()->route('subscription.index'); + } + } + public function render() + { + return view('livewire.subscription.show'); + } +} diff --git a/app/Livewire/Team/Member.php b/app/Livewire/Team/Member.php index 7d02dbf66..0f0774898 100644 --- a/app/Livewire/Team/Member.php +++ b/app/Livewire/Team/Member.php @@ -16,6 +16,11 @@ class Member extends Component $this->dispatch('reloadWindow'); } + public function makeOwner() + { + $this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => 'owner']); + $this->dispatch('reloadWindow'); + } public function makeReadonly() { $this->member->teams()->updateExistingPivot(currentTeam()->id, ['role' => 'member']); @@ -26,7 +31,7 @@ class Member extends Component { $this->member->teams()->detach(currentTeam()); Cache::forget("team:{$this->member->id}"); - Cache::remember('team:' . $this->member->id, 3600, function() { + Cache::remember('team:' . $this->member->id, 3600, function () { return $this->member->teams()->first(); }); $this->dispatch('reloadWindow'); diff --git a/app/Models/Service.php b/app/Models/Service.php index 246e812c2..9fa175bae 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -6,7 +6,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Collection; -use Illuminate\Support\Str; class Service extends BaseModel { @@ -28,47 +27,73 @@ class Service extends BaseModel { return $this->morphToMany(Tag::class, 'taggable'); } - public function status() { - $foundRunning = false; - $isDegraded = false; - $foundRestaring = false; + public function status() + { $applications = $this->applications; $databases = $this->databases; + + $complexStatus = null; + $complexHealth = null; + foreach ($applications as $application) { if ($application->exclude_from_status) { continue; } - if (Str::of($application->status)->startsWith('running')) { - $foundRunning = true; - } else if (Str::of($application->status)->startsWith('restarting')) { - $foundRestaring = true; + $status = str($application->status)->before('(')->trim(); + $health = str($application->status)->between('(', ')')->trim(); + if ($complexStatus === 'degraded') { + continue; + } + if ($status->startsWith('running')) { + if ($complexStatus === 'exited') { + $complexStatus = 'degraded'; + } else { + $complexStatus = 'running'; + } + } else if ($status->startsWith('restarting')) { + $complexStatus = 'degraded'; + } else if ($status->startsWith('exited')) { + $complexStatus = 'exited'; + } + if ($health->value() === 'healthy') { + if ($complexHealth === 'unhealthy') { + continue; + } + $complexHealth = 'healthy'; } else { - $isDegraded = true; + $complexHealth = 'unhealthy'; } } foreach ($databases as $database) { if ($database->exclude_from_status) { continue; } - if (Str::of($database->status)->startsWith('running')) { - $foundRunning = true; - } else if (Str::of($database->status)->startsWith('restarting')) { - $foundRestaring = true; + $status = str($database->status)->before('(')->trim(); + $health = str($database->status)->between('(', ')')->trim(); + if ($complexStatus === 'degraded') { + continue; + } + if ($status->startsWith('running')) { + if ($complexStatus === 'exited') { + $complexStatus = 'degraded'; + } else { + $complexStatus = 'running'; + } + } else if ($status->startsWith('restarting')) { + $complexStatus = 'degraded'; + } else if ($status->startsWith('exited')) { + $complexStatus = 'exited'; + } + if ($health->value() === 'healthy') { + if ($complexHealth === 'unhealthy') { + continue; + } + $complexHealth = 'healthy'; } else { - $isDegraded = true; + $complexHealth = 'unhealthy'; } } - if ($foundRestaring) { - return 'degraded'; - } - if ($foundRunning && !$isDegraded) { - return 'running'; - } else if ($foundRunning && $isDegraded) { - return 'degraded'; - } else if (!$foundRunning && !$isDegraded) { - return 'exited'; - } - return 'exited'; + return "{$complexStatus}:{$complexHealth}"; } public function extraFields() { @@ -414,7 +439,7 @@ class Service extends BaseModel public function documentation() { $services = getServiceTemplates(); - $service = data_get($services, Str::of($this->name)->beforeLast('-')->value, []); + $service = data_get($services, str($this->name)->beforeLast('-')->value, []); return data_get($service, 'documentation', config('constants.docs.base_url')); } public function applications() diff --git a/app/Models/Subscription.php b/app/Models/Subscription.php index cd35dc477..4b8c6d70e 100644 --- a/app/Models/Subscription.php +++ b/app/Models/Subscription.php @@ -30,8 +30,7 @@ class Subscription extends Model if (in_array($subscription, $ultimate)) { return 'ultimate'; } - } - if (isStripe()) { + } else if (isStripe()) { if (!$this->stripe_plan_id) { return 'zero'; } @@ -55,7 +54,7 @@ class Subscription extends Model }; })->first(); if ($stripePlanId) { - return Str::of($stripePlanId)->after('stripe_price_id_')->before('_')->lower(); + return str($stripePlanId)->after('stripe_price_id_')->before('_')->lower(); } } return 'zero'; diff --git a/app/Models/User.php b/app/Models/User.php index c099eb2b6..f8507a6b9 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -67,7 +67,7 @@ class User extends Authenticatable implements SendsEmail 'team_id' => session('currentTeam')->id ]); - return new NewAccessToken($token, $token->getKey().'|'.$plainTextToken); + return new NewAccessToken($token, $token->getKey() . '|' . $plainTextToken); } public function teams() { @@ -103,9 +103,13 @@ class User extends Authenticatable implements SendsEmail public function isAdmin() { - return data_get($this->pivot, 'role') === 'admin' || data_get($this->pivot, 'role') === 'owner'; + return $this->role() === 'admin' || $this->role() === 'owner'; } + public function isOwner() + { + return $this->role() === 'owner'; + } public function isAdminFromSession() { if (auth()->user()->id === 0) { @@ -155,6 +159,9 @@ class User extends Authenticatable implements SendsEmail public function role() { - return session('currentTeam')->pivot->role; + if (data_get($this, 'pivot')) { + return $this->pivot->role; + } + return auth()->user()->teams->where('id', currentTeam()->id)->first()->pivot->role; } } diff --git a/bootstrap/helpers/subscriptions.php b/bootstrap/helpers/subscriptions.php index 47ea21e46..a26bed75b 100644 --- a/bootstrap/helpers/subscriptions.php +++ b/bootstrap/helpers/subscriptions.php @@ -109,7 +109,7 @@ function isPaddle() function getStripeCustomerPortalSession(Team $team) { Stripe::setApiKey(config('subscription.stripe_api_key')); - $return_url = route('team.index'); + $return_url = route('subscription.show'); $stripe_customer_id = data_get($team,'subscription.stripe_customer_id'); if (!$stripe_customer_id) { return null; @@ -123,7 +123,7 @@ function getStripeCustomerPortalSession(Team $team) function allowedPathsForUnsubscribedAccounts() { return [ - 'subscription', + 'subscription/new', 'login', 'logout', 'waitlist', diff --git a/config/sentry.php b/config/sentry.php index a183d2d97..00c5f77de 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -7,7 +7,7 @@ return [ // The release version of your application // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) - 'release' => '4.0.0-beta.223', + 'release' => '4.0.0-beta.224', // When left empty or `null` the Laravel environment will be used 'environment' => config('app.env'), diff --git a/config/subscription.php b/config/subscription.php index 677689ff1..96a9a8e1c 100644 --- a/config/subscription.php +++ b/config/subscription.php @@ -13,6 +13,12 @@ return [ 'stripe_price_id_ultimate_yearly' => env('STRIPE_PRICE_ID_ULTIMATE_YEARLY', null), 'stripe_excluded_plans' => env('STRIPE_EXCLUDED_PLANS', null), + 'stripe_price_id_basic_monthly_old' => env('STRIPE_PRICE_ID_BASIC_MONTHLY_OLD', null), + 'stripe_price_id_basic_yearly_old' => env('STRIPE_PRICE_ID_BASIC_YEARLY_OLD', null), + 'stripe_price_id_pro_monthly_old' => env('STRIPE_PRICE_ID_PRO_MONTHLY_OLD', null), + 'stripe_price_id_pro_yearly_old' => env('STRIPE_PRICE_ID_PRO_YEARLY_OLD', null), + 'stripe_price_id_ultimate_monthly_old' => env('STRIPE_PRICE_ID_ULTIMATE_MONTHLY_OLD', null), + 'stripe_price_id_ultimate_yearly_old' => env('STRIPE_PRICE_ID_ULTIMATE_YEARLY_OLD', null), // Paddle 'paddle_vendor_id' => env('PADDLE_VENDOR_ID', null), diff --git a/config/version.php b/config/version.php index 6ad89f693..c4e13f9de 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ . + --> + + \ No newline at end of file diff --git a/resources/views/components/navbar.blade.php b/resources/views/components/navbar.blade.php index 0713ca503..3bd1730be 100644 --- a/resources/views/components/navbar.blade.php +++ b/resources/views/components/navbar.blade.php @@ -44,9 +44,10 @@
Start self-hosting without limits with our OSS version. Same features as the paid version, but you have to manage by yourself.
-Start self-hosting in - the cloud - with a - single - server. +
Begin hosting your own services in the + cloud.
Expand your business or set up your own hosting + environment.
Easily manage complex infrastructures in a + single location.