fix: use Auth(), add new db proxy stop event refactor clickhouse view

This commit is contained in:
Andras Bacsai
2024-11-04 14:18:16 +01:00
parent 1ab459a09b
commit 7fb1a1fc75
22 changed files with 236 additions and 123 deletions

View File

@@ -2,7 +2,7 @@
namespace App\Actions\Database; namespace App\Actions\Database;
use App\Events\DatabaseStatusChanged; use App\Events\DatabaseProxyStopped;
use App\Models\ServiceDatabase; use App\Models\ServiceDatabase;
use App\Models\StandaloneClickhouse; use App\Models\StandaloneClickhouse;
use App\Models\StandaloneDragonfly; use App\Models\StandaloneDragonfly;
@@ -27,7 +27,11 @@ class StopDatabaseProxy
$server = data_get($database, 'service.server'); $server = data_get($database, 'service.server');
} }
instant_remote_process(["docker rm -f {$uuid}-proxy"], $server); instant_remote_process(["docker rm -f {$uuid}-proxy"], $server);
$database->is_public = false;
$database->save(); $database->save();
DatabaseStatusChanged::dispatch();
DatabaseProxyStopped::dispatch();
} }
} }

View File

@@ -0,0 +1,35 @@
<?php
namespace App\Events;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Auth;
class DatabaseProxyStopped implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $teamId;
public function __construct($teamId = null)
{
if (is_null($teamId)) {
$teamId = Auth::user()->currentTeam()->id ?? null;
}
if (is_null($teamId)) {
throw new \Exception('Team id is null');
}
$this->teamId = $teamId;
}
public function broadcastOn(): array
{
return [
new PrivateChannel("team.{$this->teamId}"),
];
}
}

View File

@@ -7,27 +7,29 @@ use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Auth;
class DatabaseStatusChanged implements ShouldBroadcast class DatabaseStatusChanged implements ShouldBroadcast
{ {
use Dispatchable, InteractsWithSockets, SerializesModels; use Dispatchable, InteractsWithSockets, SerializesModels;
public ?string $userId = null; public $userId = null;
public function __construct($userId = null) public function __construct($userId = null)
{ {
if (is_null($userId)) { if (is_null($userId)) {
$userId = auth()->user()->id ?? null; $userId = Auth::id() ?? null;
} }
if (is_null($userId)) { if (is_null($userId)) {
return false; return false;
} }
$this->userId = $userId; $this->userId = $userId;
} }
public function broadcastOn(): ?array public function broadcastOn(): ?array
{ {
if ($this->userId) { if (! is_null($this->userId)) {
return [ return [
new PrivateChannel("user.{$this->userId}"), new PrivateChannel("user.{$this->userId}"),
]; ];

View File

@@ -7,6 +7,7 @@ use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Auth;
class ServiceStatusChanged implements ShouldBroadcast class ServiceStatusChanged implements ShouldBroadcast
{ {
@@ -17,7 +18,7 @@ class ServiceStatusChanged implements ShouldBroadcast
public function __construct($userId = null) public function __construct($userId = null)
{ {
if (is_null($userId)) { if (is_null($userId)) {
$userId = auth()->user()->id ?? null; $userId = Auth::id() ?? null;
} }
if (is_null($userId)) { if (is_null($userId)) {
return false; return false;

View File

@@ -131,7 +131,7 @@ class Controller extends BaseController
} }
$user->teams()->attach($invitation->team->id, ['role' => $invitation->role]); $user->teams()->attach($invitation->team->id, ['role' => $invitation->role]);
$invitation->delete(); $invitation->delete();
if (auth()->user()?->id !== $user->id) { if (Auth::id() !== $user->id) {
return redirect()->route('login'); return redirect()->route('login');
} }
refreshSession($invitation->team); refreshSession($invitation->team);
@@ -146,10 +146,10 @@ class Controller extends BaseController
{ {
$invitation = TeamInvitation::whereUuid(request()->route('uuid'))->firstOrFail(); $invitation = TeamInvitation::whereUuid(request()->route('uuid'))->firstOrFail();
$user = User::whereEmail($invitation->email)->firstOrFail(); $user = User::whereEmail($invitation->email)->firstOrFail();
if (is_null(auth()->user())) { if (is_null(Auth::user())) {
return redirect()->route('login'); return redirect()->route('login');
} }
if (auth()->user()->id !== $user->id) { if (Auth::id() !== $user->id) {
abort(401); abort(401);
} }
$invitation->delete(); $invitation->delete();

View File

@@ -3,7 +3,9 @@
namespace App\Livewire\Admin; namespace App\Livewire\Admin;
use App\Models\User; use App\Models\User;
use Illuminate\Container\Attributes\Auth as AttributesAuth;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Livewire\Component; use Livewire\Component;
@@ -23,7 +25,7 @@ class Index extends Component
return redirect()->route('dashboard'); return redirect()->route('dashboard');
} }
if (auth()->user()->id !== 0) { if (Auth::id() !== 0) {
return redirect()->route('dashboard'); return redirect()->route('dashboard');
} }
$this->getSubscribers(); $this->getSubscribers();
@@ -51,13 +53,13 @@ class Index extends Component
public function switchUser(int $user_id) public function switchUser(int $user_id)
{ {
if (auth()->user()->id !== 0) { if (AttributesAuth::id() !== 0) {
return redirect()->route('dashboard'); return redirect()->route('dashboard');
} }
$user = User::find($user_id); $user = User::find($user_id);
$team_to_switch_to = $user->teams->first(); $team_to_switch_to = $user->teams->first();
Cache::forget("team:{$user->id}"); Cache::forget("team:{$user->id}");
auth()->login($user); Auth::login($user);
refreshSession($team_to_switch_to); refreshSession($team_to_switch_to);
return redirect(request()->header('Referer')); return redirect(request()->header('Referer'));

View File

@@ -3,6 +3,7 @@
namespace App\Livewire; namespace App\Livewire;
use App\Models\InstanceSettings; use App\Models\InstanceSettings;
use Illuminate\Container\Attributes\Auth as AttributesAuth;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
@@ -31,7 +32,7 @@ class NavbarDeleteTeam extends Component
$currentTeam->delete(); $currentTeam->delete();
$currentTeam->members->each(function ($user) use ($currentTeam) { $currentTeam->members->each(function ($user) use ($currentTeam) {
if ($user->id === auth()->user()->id) { if ($user->id === AttributesAuth::id()) {
return; return;
} }
$user->teams()->detach($currentTeam); $user->teams()->detach($currentTeam);

View File

@@ -2,6 +2,7 @@
namespace App\Livewire\Profile; namespace App\Livewire\Profile;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules\Password; use Illuminate\Validation\Rules\Password;
use Livewire\Attributes\Validate; use Livewire\Attributes\Validate;
@@ -24,9 +25,9 @@ class Index extends Component
public function mount() public function mount()
{ {
$this->userId = auth()->user()->id; $this->userId = Auth::id();
$this->name = auth()->user()->name; $this->name = Auth::user()->name;
$this->email = auth()->user()->email; $this->email = Auth::user()->email;
} }
public function submit() public function submit()
@@ -35,7 +36,7 @@ class Index extends Component
$this->validate([ $this->validate([
'name' => 'required', 'name' => 'required',
]); ]);
auth()->user()->update([ Auth::user()->update([
'name' => $this->name, 'name' => $this->name,
]); ]);

View File

@@ -7,6 +7,8 @@ use App\Actions\Database\StopDatabaseProxy;
use App\Models\Server; use App\Models\Server;
use App\Models\StandaloneClickhouse; use App\Models\StandaloneClickhouse;
use Exception; use Exception;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Rule;
use Livewire\Component; use Livewire\Component;
class General extends Component class General extends Component
@@ -15,54 +17,106 @@ class General extends Component
public StandaloneClickhouse $database; public StandaloneClickhouse $database;
public ?string $db_url = null; #[Rule(['required', 'string'])]
public string $name;
public ?string $db_url_public = null; #[Rule(['nullable', 'string'])]
public ?string $description = null;
protected $listeners = ['refresh']; #[Rule(['required', 'string'])]
public string $clickhouseAdminUser;
protected $rules = [ #[Rule(['required', 'string'])]
'database.name' => 'required', public string $clickhouseAdminPassword;
'database.description' => 'nullable',
'database.clickhouse_admin_user' => 'required',
'database.clickhouse_admin_password' => 'required',
'database.image' => 'required',
'database.ports_mappings' => 'nullable',
'database.is_public' => 'nullable|boolean',
'database.public_port' => 'nullable|integer',
'database.is_log_drain_enabled' => 'nullable|boolean',
'database.custom_docker_run_options' => 'nullable',
];
protected $validationAttributes = [ #[Rule(['required', 'string'])]
'database.name' => 'Name', public string $image;
'database.description' => 'Description',
'database.clickhouse_admin_user' => 'Postgres User', #[Rule(['nullable', 'string'])]
'database.clickhouse_admin_password' => 'Postgres Password', public ?string $portsMappings = null;
'database.image' => 'Image',
'database.ports_mappings' => 'Port Mapping', #[Rule(['nullable', 'boolean'])]
'database.is_public' => 'Is Public', public ?bool $isPublic = null;
'database.public_port' => 'Public Port',
'database.custom_docker_run_options' => 'Custom Docker Run Options', #[Rule(['nullable', 'integer'])]
]; public ?int $publicPort = null;
#[Rule(['nullable', 'string'])]
public ?string $customDockerRunOptions = null;
#[Rule(['nullable', 'string'])]
public ?string $dbUrl = null;
#[Rule(['nullable', 'string'])]
public ?string $dbUrlPublic = null;
#[Rule(['nullable', 'boolean'])]
public bool $isLogDrainEnabled = false;
public function getListeners()
{
$teamId = Auth::user()->currentTeam()->id;
return [
"echo-private:team.{$teamId},DatabaseProxyStopped" => 'databaseProxyStopped',
];
}
public function mount() public function mount()
{ {
$this->db_url = $this->database->internal_db_url; try {
$this->db_url_public = $this->database->external_db_url; $this->syncData();
$this->server = data_get($this->database, 'destination.server'); $this->server = data_get($this->database, 'destination.server');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function syncData(bool $toModel = false)
{
if ($toModel) {
$this->validate();
$this->database->name = $this->name;
$this->database->description = $this->description;
$this->database->clickhouse_admin_user = $this->clickhouseAdminUser;
$this->database->clickhouse_admin_password = $this->clickhouseAdminPassword;
$this->database->image = $this->image;
$this->database->ports_mappings = $this->portsMappings;
$this->database->is_public = $this->isPublic;
$this->database->public_port = $this->publicPort;
$this->database->custom_docker_run_options = $this->customDockerRunOptions;
$this->database->is_log_drain_enabled = $this->isLogDrainEnabled;
$this->database->save();
$this->dbUrl = $this->database->internal_db_url;
$this->dbUrlPublic = $this->database->external_db_url;
} else {
$this->name = $this->database->name;
$this->description = $this->database->description;
$this->clickhouseAdminUser = $this->database->clickhouse_admin_user;
$this->clickhouseAdminPassword = $this->database->clickhouse_admin_password;
$this->image = $this->database->image;
$this->portsMappings = $this->database->ports_mappings;
$this->isPublic = $this->database->is_public;
$this->publicPort = $this->database->public_port;
$this->customDockerRunOptions = $this->database->custom_docker_run_options;
$this->isLogDrainEnabled = $this->database->is_log_drain_enabled;
$this->dbUrl = $this->database->internal_db_url;
$this->dbUrlPublic = $this->database->external_db_url;
}
} }
public function instantSaveAdvanced() public function instantSaveAdvanced()
{ {
try { try {
if (! $this->server->isLogDrainEnabled()) { if (! $this->server->isLogDrainEnabled()) {
$this->database->is_log_drain_enabled = false; $this->isLogDrainEnabled = false;
$this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.');
return; return;
} }
$this->database->save(); $this->syncData(true);
$this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'Database updated.');
$this->dispatch('success', 'You need to restart the service for the changes to take effect.'); $this->dispatch('success', 'You need to restart the service for the changes to take effect.');
} catch (Exception $e) { } catch (Exception $e) {
@@ -73,16 +127,16 @@ class General extends Component
public function instantSave() public function instantSave()
{ {
try { try {
if ($this->database->is_public && ! $this->database->public_port) { if ($this->isPublic && ! $this->publicPort) {
$this->dispatch('error', 'Public port is required.'); $this->dispatch('error', 'Public port is required.');
$this->database->is_public = false; $this->isPublic = false;
return; return;
} }
if ($this->database->is_public) { if ($this->isPublic) {
if (! str($this->database->status)->startsWith('running')) { if (! str($this->database->status)->startsWith('running')) {
$this->dispatch('error', 'Database must be started to be publicly accessible.'); $this->dispatch('error', 'Database must be started to be publicly accessible.');
$this->database->is_public = false; $this->isPublic = false;
return; return;
} }
@@ -92,28 +146,28 @@ class General extends Component
StopDatabaseProxy::run($this->database); StopDatabaseProxy::run($this->database);
$this->dispatch('success', 'Database is no longer publicly accessible.'); $this->dispatch('success', 'Database is no longer publicly accessible.');
} }
$this->db_url_public = $this->database->external_db_url; $this->dbUrlPublic = $this->database->external_db_url;
$this->database->save(); $this->syncData(true);
} catch (\Throwable $e) { } catch (\Throwable $e) {
$this->database->is_public = ! $this->database->is_public; $this->isPublic = ! $this->isPublic;
$this->syncData(true);
return handleError($e, $this); return handleError($e, $this);
} }
} }
public function refresh(): void public function databaseProxyStopped()
{ {
$this->database->refresh(); $this->syncData();
} }
public function submit() public function submit()
{ {
try { try {
if (str($this->database->public_port)->isEmpty()) { if (str($this->publicPort)->isEmpty()) {
$this->database->public_port = null; $this->publicPort = null;
} }
$this->validate(); $this->syncData(true);
$this->database->save();
$this->dispatch('success', 'Database updated.'); $this->dispatch('success', 'Database updated.');
} catch (Exception $e) { } catch (Exception $e) {
return handleError($e, $this); return handleError($e, $this);

View File

@@ -6,6 +6,7 @@ use App\Actions\Database\RestartDatabase;
use App\Actions\Database\StartDatabase; use App\Actions\Database\StartDatabase;
use App\Actions\Database\StopDatabase; use App\Actions\Database\StopDatabase;
use App\Actions\Docker\GetContainersStatus; use App\Actions\Docker\GetContainersStatus;
use Illuminate\Support\Facades\Auth;
use Livewire\Component; use Livewire\Component;
class Heading extends Component class Heading extends Component
@@ -18,7 +19,7 @@ class Heading extends Component
public function getListeners() public function getListeners()
{ {
$userId = auth()->user()->id; $userId = Auth::id();
return [ return [
"echo-private:user.{$userId},DatabaseStatusChanged" => 'activityFinished', "echo-private:user.{$userId},DatabaseStatusChanged" => 'activityFinished',

View File

@@ -3,6 +3,7 @@
namespace App\Livewire\Project\Database; namespace App\Livewire\Project\Database;
use App\Models\Server; use App\Models\Server;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Livewire\Component; use Livewire\Component;
@@ -46,7 +47,7 @@ class Import extends Component
public function getListeners() public function getListeners()
{ {
$userId = auth()->user()->id; $userId = Auth::id();
return [ return [
"echo-private:user.{$userId},DatabaseStatusChanged" => '$refresh', "echo-private:user.{$userId},DatabaseStatusChanged" => '$refresh',

View File

@@ -4,6 +4,7 @@ namespace App\Livewire\Project\Service;
use App\Actions\Docker\GetContainersStatus; use App\Actions\Docker\GetContainersStatus;
use App\Models\Service; use App\Models\Service;
use Illuminate\Support\Facades\Auth;
use Livewire\Component; use Livewire\Component;
class Configuration extends Component class Configuration extends Component
@@ -20,7 +21,7 @@ class Configuration extends Component
public function getListeners() public function getListeners()
{ {
$userId = auth()->user()->id; $userId = Auth::id();
return [ return [
"echo-private:user.{$userId},ServiceStatusChanged" => 'check_status', "echo-private:user.{$userId},ServiceStatusChanged" => 'check_status',

View File

@@ -7,6 +7,7 @@ use App\Actions\Service\StopService;
use App\Actions\Shared\PullImage; use App\Actions\Shared\PullImage;
use App\Events\ServiceStatusChanged; use App\Events\ServiceStatusChanged;
use App\Models\Service; use App\Models\Service;
use Illuminate\Support\Facades\Auth;
use Livewire\Component; use Livewire\Component;
use Spatie\Activitylog\Models\Activity; use Spatie\Activitylog\Models\Activity;
@@ -34,7 +35,7 @@ class Navbar extends Component
public function getListeners() public function getListeners()
{ {
$userId = auth()->user()->id; $userId = Auth::id();
return [ return [
"echo-private:user.{$userId},ServiceStatusChanged" => 'serviceStarted', "echo-private:user.{$userId},ServiceStatusChanged" => 'serviceStarted',

View File

@@ -2,6 +2,7 @@
namespace App\Livewire\Subscription; namespace App\Livewire\Subscription;
use Illuminate\Support\Facades\Auth;
use Livewire\Component; use Livewire\Component;
use Stripe\Checkout\Session; use Stripe\Checkout\Session;
use Stripe\Stripe; use Stripe\Stripe;
@@ -26,7 +27,7 @@ class PricingPlans extends Component
$payload = [ $payload = [
'allow_promotion_codes' => true, 'allow_promotion_codes' => true,
'billing_address_collection' => 'required', 'billing_address_collection' => 'required',
'client_reference_id' => auth()->user()->id.':'.currentTeam()->id, 'client_reference_id' => Auth::id().':'.currentTeam()->id,
'line_items' => [[ 'line_items' => [[
'price' => $priceId, 'price' => $priceId,
'adjustable_quantity' => [ 'adjustable_quantity' => [
@@ -43,7 +44,7 @@ class PricingPlans extends Component
], ],
'subscription_data' => [ 'subscription_data' => [
'metadata' => [ 'metadata' => [
'user_id' => auth()->user()->id, 'user_id' => Auth::id(),
'team_id' => currentTeam()->id, 'team_id' => currentTeam()->id,
], ],
], ],
@@ -60,7 +61,7 @@ class PricingPlans extends Component
'name' => 'auto', 'name' => 'auto',
]; ];
} else { } else {
$payload['customer_email'] = auth()->user()->email; $payload['customer_email'] = Auth::user()->email;
} }
$session = Session::create($payload); $session = Session::create($payload);

View File

@@ -4,6 +4,7 @@ namespace App\Livewire\Team;
use App\Models\Team; use App\Models\Team;
use App\Models\TeamInvitation; use App\Models\TeamInvitation;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Livewire\Component; use Livewire\Component;
@@ -55,7 +56,7 @@ class Index extends Component
$currentTeam->delete(); $currentTeam->delete();
$currentTeam->members->each(function ($user) use ($currentTeam) { $currentTeam->members->each(function ($user) use ($currentTeam) {
if ($user->id === auth()->user()->id) { if ($user->id === Auth::id()) {
return; return;
} }
$user->teams()->detach($currentTeam); $user->teams()->detach($currentTeam);

View File

@@ -10,6 +10,7 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\URL; use Illuminate\Support\Facades\URL;
@@ -158,7 +159,7 @@ class User extends Authenticatable implements SendsEmail
public function isAdminFromSession() public function isAdminFromSession()
{ {
if (auth()->user()->id === 0) { if (Auth::id() === 0) {
return true; return true;
} }
$teams = $this->teams()->get(); $teams = $this->teams()->get();
@@ -178,9 +179,9 @@ class User extends Authenticatable implements SendsEmail
public function isInstanceAdmin() public function isInstanceAdmin()
{ {
$found_root_team = auth()->user()->teams->filter(function ($team) { $found_root_team = Auth::user()->teams->filter(function ($team) {
if ($team->id == 0) { if ($team->id == 0) {
if (! auth()->user()->isAdmin()) { if (! Auth::user()->isAdmin()) {
return false; return false;
} }
@@ -195,9 +196,9 @@ class User extends Authenticatable implements SendsEmail
public function currentTeam() public function currentTeam()
{ {
return Cache::remember('team:'.auth()->user()->id, 3600, function () { return Cache::remember('team:'.Auth::id(), 3600, function () {
if (is_null(data_get(session('currentTeam'), 'id')) && auth()->user()->teams->count() > 0) { if (is_null(data_get(session('currentTeam'), 'id')) && Auth::user()->teams->count() > 0) {
return auth()->user()->teams[0]; return Auth::user()->teams[0];
} }
return Team::find(session('currentTeam')->id); return Team::find(session('currentTeam')->id);
@@ -206,7 +207,7 @@ class User extends Authenticatable implements SendsEmail
public function otherTeams() public function otherTeams()
{ {
return auth()->user()->teams->filter(function ($team) { return Auth::user()->teams->filter(function ($team) {
return $team->id != currentTeam()->id; return $team->id != currentTeam()->id;
}); });
} }
@@ -216,7 +217,7 @@ class User extends Authenticatable implements SendsEmail
if (data_get($this, 'pivot')) { if (data_get($this, 'pivot')) {
return $this->pivot->role; return $this->pivot->role;
} }
$user = auth()->user()->teams->where('id', currentTeam()->id)->first(); $user = Auth::user()->teams->where('id', currentTeam()->id)->first();
return data_get($user, 'pivot.role'); return data_get($user, 'pivot.role');
} }

View File

@@ -35,6 +35,7 @@ use Illuminate\Mail\Message;
use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Process\Pool; use Illuminate\Process\Pool;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
@@ -100,12 +101,12 @@ function isInstanceAdmin()
function currentTeam() function currentTeam()
{ {
return auth()?->user()?->currentTeam() ?? null; return Auth::user()?->currentTeam() ?? null;
} }
function showBoarding(): bool function showBoarding(): bool
{ {
if (auth()->user()?->isMember()) { if (Auth::user()->isMember()) {
return false; return false;
} }
@@ -114,14 +115,14 @@ function showBoarding(): bool
function refreshSession(?Team $team = null): void function refreshSession(?Team $team = null): void
{ {
if (! $team) { if (! $team) {
if (auth()->user()?->currentTeam()) { if (Auth::user()->currentTeam()) {
$team = Team::find(auth()->user()->currentTeam()->id); $team = Team::find(Auth::user()->currentTeam()->id);
} else { } else {
$team = User::find(auth()->user()->id)->teams->first(); $team = User::find(Auth::id())->teams->first();
} }
} }
Cache::forget('team:'.auth()->user()->id); Cache::forget('team:'.Auth::id());
Cache::remember('team:'.auth()->user()->id, 3600, function () use ($team) { Cache::remember('team:'.Auth::id(), 3600, function () use ($team) {
return $team; return $team;
}); });
session(['currentTeam' => $team]); session(['currentTeam' => $team]);

View File

@@ -10,7 +10,7 @@
]) ])
<div @class([ <div @class([
'flex flex-row items-center gap-4 px-2 py-1 form-control min-w-fit dark:hover:bg-coolgray-100', 'flex flex-row items-center gap-4 pr-2 py-1 form-control min-w-fit dark:hover:bg-coolgray-100',
'w-full' => $fullWidth, 'w-full' => $fullWidth,
])> ])>
@if (!$hideLabel) @if (!$hideLabel)

View File

@@ -7,68 +7,75 @@
</x-forms.button> </x-forms.button>
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<x-forms.input label="Name" id="database.name" /> <x-forms.input label="Name" id="name" />
<x-forms.input label="Description" id="database.description" /> <x-forms.input label="Description" id="description" />
<x-forms.input label="Image" id="database.image" required <x-forms.input label="Image" id="image" required
helper="For all available images, check here:<br><br><a target='_blank' href='https://hub.docker.com/r/clickhouse/clickhouse-server/'>https://hub.docker.com/r/clickhouse/clickhouse-server/</a>" /> helper="For all available images, check here:<br><br><a target='_blank' href='https://hub.docker.com/r/clickhouse/clickhouse-server/'>https://hub.docker.com/r/clickhouse/clickhouse-server/</a>" />
</div> </div>
@if ($database->started_at) @if ($database->started_at)
<div class="flex gap-2"> <div class="flex gap-2">
<x-forms.input label="Initial Username" id="database.clickhouse_admin_user" <x-forms.input label="Initial Username" id="clickhouseAdminUser" placeholder="If empty: clickhouse"
placeholder="If empty: clickhouse" readonly helper="You can only change this in the database." />
<x-forms.input label="Initial Password" id="database.clickhouse_admin_password" type="password" required
readonly helper="You can only change this in the database." /> readonly helper="You can only change this in the database." />
<x-forms.input label="Initial Password" id="clickhouseAdminPassword" type="password" required readonly
helper="You can only change this in the database." />
</div> </div>
@else @else
<div class=" dark:text-warning">Please verify these values. You can only modify them before the initial <div class=" dark:text-warning">Please verify these values. You can only modify them before the initial
start. After that, you need to modify it in the database. start. After that, you need to modify it in the database.
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<x-forms.input label="Username" id="database.clickhouse_admin_user" required /> <x-forms.input label="Username" id="clickhouseAdminUser" required />
<x-forms.input label="Password" id="database.clickhouse_admin_password" type="password" required /> <x-forms.input label="Password" id="clickhouseAdminPassword" type="password" required />
</div> </div>
@endif @endif
<x-forms.input <x-forms.input
helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>" helper="You can add custom docker run options that will be used when your container is started.<br>Note: Not all options are supported, as they could mess up Coolify's automation and could cause bad experience for users.<br><br>Check the <a class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/docker/custom-commands'>docs.</a>"
placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k" placeholder="--cap-add SYS_ADMIN --device=/dev/fuse --security-opt apparmor:unconfined --ulimit nofile=1024:1024 --tmpfs /run:rw,noexec,nosuid,size=65536k"
id="database.custom_docker_run_options" label="Custom Docker Options" /> id="customDockerRunOptions" label="Custom Docker Options" />
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<h3 class="py-2">Network</h3> <h3 class="py-2">Network</h3>
<div class="flex items-end gap-2"> <div class="flex items-end gap-2">
<x-forms.input placeholder="3000:5432" id="database.ports_mappings" label="Ports Mappings" <x-forms.input placeholder="3000:5432" id="portsMappings" label="Ports Mappings"
helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433" /> helper="A comma separated list of ports you would like to map to the host system.<br><span class='inline-block font-bold dark:text-warning'>Example</span>3000:5432,3002:5433" />
</div> </div>
<x-forms.input label="Clickhouse URL (internal)" <x-forms.input label="Clickhouse URL (internal)"
helper="If you change the user/password/port, this could be different. This is with the default values." helper="If you change the user/password/port, this could be different. This is with the default values."
type="password" readonly wire:model="db_url" /> type="password" readonly wire:model="dbUrl" />
@if ($db_url_public) @if ($dbUrlPublic)
<x-forms.input label="Clickhouse URL (public)" <x-forms.input label="Clickhouse URL (public)"
helper="If you change the user/password/port, this could be different. This is with the default values." helper="If you change the user/password/port, this could be different. This is with the default values."
type="password" readonly wire:model="db_url_public" /> type="password" readonly wire:model="dbUrlPublic" />
@else
<x-forms.input label="Clickhouse URL (public)"
helper="If you change the user/password/port, this could be different. This is with the default values."
readonly value="Starting the database will generate this." />
@endif @endif
</div> </div>
<div> <div>
<h3 class="py-2">Proxy</h3> <div class="flex flex-col py-2 w-64">
<div class="flex items-end gap-2"> <div class="flex items-center gap-2 pb-2">
<x-forms.input placeholder="5432" disabled="{{ data_get($database, 'is_public') }}" <h3>Proxy</h3>
id="database.public_port" label="Public Port" /> @if ($isPublic)
<x-slide-over fullScreen> <x-slide-over fullScreen>
<x-slot:title>Proxy Logs</x-slot:title> <x-slot:title>Proxy Logs</x-slot:title>
<x-slot:content> <x-slot:content>
<livewire:project.shared.get-logs :server="$server" :resource="$database" <livewire:project.shared.get-logs :server="$server" :resource="$database"
container="{{ data_get($database, 'uuid') }}-proxy" lazy /> container="{{ data_get($database, 'uuid') }}-proxy" lazy />
</x-slot:content> </x-slot:content>
<x-forms.button disabled="{{ !data_get($database, 'is_public') }}" @click="slideOverOpen=true" <x-forms.button disabled="{{ !$isPublic }}"
class="w-28">Proxy Logs</x-forms.button> @click="slideOverOpen=true">Logs</x-forms.button>
</x-slide-over> </x-slide-over>
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available" /> @endif
</div>
<x-forms.checkbox instantSave id="isPublic" label="Make it publicly available" />
</div> </div>
<x-forms.input placeholder="5432" disabled="{{ $isPublic }}" id="publicPort" label="Public Port" />
</div> </div>
</form> </form>
<h3 class="pt-4">Advanced</h3> <h3 class="pt-4">Advanced</h3>
<div class="flex flex-col"> <div class="w-64">
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings." <x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."
instantSave="instantSaveAdvanced" id="database.is_log_drain_enabled" label="Drain Logs" /> instantSave="instantSaveAdvanced" id="isLogDrainEnabled" label="Drain Logs" />
</div> </div>
</div> </div>

View File

@@ -47,9 +47,6 @@
<x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available" /> <x-forms.checkbox instantSave id="database.is_public" label="Make it publicly available" />
</div> </div>
</div> </div>
{{-- <x-forms.textarea
helper="<a target='_blank' class='underline dark:text-white' href='https://raw.githubusercontent.com/Snapchat/KeyDB/unstable/keydb.conf'>KeyDB Default Configuration</a>"
label="Custom Dragonfly Configuration" rows="10" id="database.keydb_conf" /> --}}
<h3 class="pt-4">Advanced</h3> <h3 class="pt-4">Advanced</h3>
<div class="flex flex-col"> <div class="flex flex-col">
<x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings." <x-forms.checkbox helper="Drain logs to your configured log drain endpoint in your Server settings."

View File

@@ -1,6 +1,6 @@
<tr @class([ <tr @class([
'dark:text-white text-black dark:bg-coolblack dark:hover:bg-coolgray-100', 'dark:text-white text-black dark:bg-coolblack dark:hover:bg-coolgray-100',
'dark:bg-coolgray-100 bg-neutral-200' => $member->id == auth()->user()->id, 'dark:bg-coolgray-100 bg-neutral-200' => $member->id == Auth::id(),
])> ])>
<td class="px-5 py-4 text-sm whitespace-nowrap"> <td class="px-5 py-4 text-sm whitespace-nowrap">
{{ $member->name }} {{ $member->name }}
@@ -12,9 +12,9 @@
{{ data_get($member, 'pivot.role') }} {{ data_get($member, 'pivot.role') }}
</td> </td>
<td class="flex gap-2 px-5 py-4 text-sm whitespace-nowrap"> <td class="flex gap-2 px-5 py-4 text-sm whitespace-nowrap">
@if (auth()->user()->isAdminFromSession()) @if (Auth::user()->isAdminFromSession())
@if ($member->id !== auth()->user()->id) @if ($member->id !== Auth::id())
@if (auth()->user()->isOwner()) @if (Auth::user()->isOwner())
@if (data_get($member, 'pivot.role') === 'owner') @if (data_get($member, 'pivot.role') === 'owner')
<x-forms.button wire:click="makeAdmin">To Admin</x-forms.button> <x-forms.button wire:click="makeAdmin">To Admin</x-forms.button>
<x-forms.button wire:click="makeReadonly">To Member</x-forms.button> <x-forms.button wire:click="makeReadonly">To Member</x-forms.button>
@@ -30,7 +30,7 @@
<x-forms.button wire:click="makeAdmin">To Admin</x-forms.button> <x-forms.button wire:click="makeAdmin">To Admin</x-forms.button>
<x-forms.button isError wire:click="remove">Remove</x-forms.button> <x-forms.button isError wire:click="remove">Remove</x-forms.button>
@endif @endif
@elseif (auth()->user()->isAdmin()) @elseif (Auth::user()->isAdmin())
@if (data_get($member, 'pivot.role') === 'admin') @if (data_get($member, 'pivot.role') === 'admin')
<x-forms.button wire:click="makeReadonly">To Member</x-forms.button> <x-forms.button wire:click="makeReadonly">To Member</x-forms.button>
<x-forms.button isError wire:click="remove">Remove</x-forms.button> <x-forms.button isError wire:click="remove">Remove</x-forms.button>

View File

@@ -12,6 +12,7 @@
*/ */
use App\Models\User; use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Broadcast; use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('team.{teamId}', function (User $user, int $teamId) { Broadcast::channel('team.{teamId}', function (User $user, int $teamId) {
@@ -23,7 +24,7 @@ Broadcast::channel('team.{teamId}', function (User $user, int $teamId) {
}); });
Broadcast::channel('user.{userId}', function (User $user) { Broadcast::channel('user.{userId}', function (User $user) {
if ($user->id === auth()->user()->id) { if ($user->id === Auth::id()) {
return true; return true;
} }