mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-12 22:14:26 +00:00
fix(auth): enforce authorization checks across API and Livewire components
- Add authorization checks to API controller endpoints (view, create, update, delete) - Wrap Livewire component methods with try-catch for consistent error handling - Add AuthorizesRequests trait to components requiring authorization checks - Ensure all sensitive operations verify user permissions before execution - Implement unified error handling with handleError() helper function
This commit is contained in:
1 parent
12f8f80eb1
commit
86b05b902a
84 files changed
+4046
-1055
No files matched your search
@@ -176,6 +176,7 @@ class CloudProviderTokensController extends Controller
|
||||
if (is_null($token)) {
|
||||
return response()->json(['message' => 'Cloud provider token not found.'], 404);
|
||||
}
|
||||
$this->authorize('view', $token);
|
||||
|
||||
return response()->json($this->removeSensitiveData($token));
|
||||
}
|
||||
@@ -242,6 +243,7 @@ class CloudProviderTokensController extends Controller
|
||||
if (is_null($teamId)) {
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
$this->authorize('create', [CloudProviderToken::class]);
|
||||
|
||||
$return = validateIncomingRequest($request);
|
||||
if ($return instanceof \Illuminate\Http\JsonResponse) {
|
||||
@@ -386,6 +388,7 @@ class CloudProviderTokensController extends Controller
|
||||
if (! $token) {
|
||||
return response()->json(['message' => 'Cloud provider token not found.'], 404);
|
||||
}
|
||||
$this->authorize('update', $token);
|
||||
|
||||
$token->update(array_intersect_key($body, array_flip($allowedFields)));
|
||||
|
||||
@@ -459,6 +462,7 @@ class CloudProviderTokensController extends Controller
|
||||
if (! $token) {
|
||||
return response()->json(['message' => 'Cloud provider token not found.'], 404);
|
||||
}
|
||||
$this->authorize('delete', $token);
|
||||
|
||||
if ($token->hasServers()) {
|
||||
return response()->json(['message' => 'Cannot delete token that is used by servers.'], 400);
|
||||
|
||||
@@ -180,6 +180,7 @@ class GithubController extends Controller
|
||||
if (is_null($teamId)) {
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
$this->authorize('create', [GithubApp::class]);
|
||||
$return = validateIncomingRequest($request);
|
||||
if ($return instanceof \Illuminate\Http\JsonResponse) {
|
||||
return $return;
|
||||
@@ -555,6 +556,7 @@ class GithubController extends Controller
|
||||
$githubApp = GithubApp::where('id', $github_app_id)
|
||||
->where('team_id', $teamId)
|
||||
->firstOrFail();
|
||||
$this->authorize('update', $githubApp);
|
||||
|
||||
// Define allowed fields for update
|
||||
$allowedFields = [
|
||||
@@ -721,6 +723,7 @@ class GithubController extends Controller
|
||||
$githubApp = GithubApp::where('id', $github_app_id)
|
||||
->where('team_id', $teamId)
|
||||
->firstOrFail();
|
||||
$this->authorize('delete', $githubApp);
|
||||
|
||||
// Check if the GitHub app is being used by any applications
|
||||
if ($githubApp->applications->isNotEmpty()) {
|
||||
|
||||
@@ -548,6 +548,7 @@ class HetznerController extends Controller
|
||||
if (is_null($teamId)) {
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
$this->authorize('create', [Server::class]);
|
||||
|
||||
$return = validateIncomingRequest($request);
|
||||
if ($return instanceof \Illuminate\Http\JsonResponse) {
|
||||
|
||||
@@ -96,6 +96,7 @@ class ProjectController extends Controller
|
||||
if (! $project) {
|
||||
return response()->json(['message' => 'Project not found.'], 404);
|
||||
}
|
||||
$this->authorize('view', $project);
|
||||
|
||||
$project->load(['environments']);
|
||||
|
||||
@@ -232,6 +233,7 @@ class ProjectController extends Controller
|
||||
if (is_null($teamId)) {
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
$this->authorize('create', [Project::class]);
|
||||
|
||||
$return = validateIncomingRequest($request);
|
||||
if ($return instanceof \Illuminate\Http\JsonResponse) {
|
||||
@@ -378,6 +380,7 @@ class ProjectController extends Controller
|
||||
if (! $project) {
|
||||
return response()->json(['message' => 'Project not found.'], 404);
|
||||
}
|
||||
$this->authorize('update', $project);
|
||||
|
||||
$project->update($request->only($allowedFields));
|
||||
|
||||
@@ -455,6 +458,7 @@ class ProjectController extends Controller
|
||||
if (! $project) {
|
||||
return response()->json(['message' => 'Project not found.'], 404);
|
||||
}
|
||||
$this->authorize('delete', $project);
|
||||
if (! $project->isEmpty()) {
|
||||
return response()->json(['message' => 'Project has resources, so it cannot be deleted.'], 400);
|
||||
}
|
||||
@@ -630,6 +634,7 @@ class ProjectController extends Controller
|
||||
if (! $project) {
|
||||
return response()->json(['message' => 'Project not found.'], 404);
|
||||
}
|
||||
$this->authorize('update', $project);
|
||||
|
||||
$existingEnvironment = $project->environments()->where('name', $request->name)->first();
|
||||
if ($existingEnvironment) {
|
||||
@@ -717,6 +722,7 @@ class ProjectController extends Controller
|
||||
if (! $environment) {
|
||||
return response()->json(['message' => 'Environment not found.'], 404);
|
||||
}
|
||||
$this->authorize('delete', $environment);
|
||||
|
||||
if (! $environment->isEmpty()) {
|
||||
return response()->json(['message' => 'Environment has resources, so it cannot be deleted.'], 400);
|
||||
|
||||
@@ -109,6 +109,7 @@ class SecurityController extends Controller
|
||||
'message' => 'Private Key not found.',
|
||||
], 404);
|
||||
}
|
||||
$this->authorize('view', $key);
|
||||
|
||||
return response()->json($this->removeSensitiveData($key));
|
||||
}
|
||||
@@ -175,6 +176,7 @@ class SecurityController extends Controller
|
||||
if (is_null($teamId)) {
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
$this->authorize('create', [PrivateKey::class]);
|
||||
$return = validateIncomingRequest($request);
|
||||
if ($return instanceof \Illuminate\Http\JsonResponse) {
|
||||
return $return;
|
||||
@@ -330,6 +332,7 @@ class SecurityController extends Controller
|
||||
'message' => 'Private Key not found.',
|
||||
], 404);
|
||||
}
|
||||
$this->authorize('update', $foundKey);
|
||||
$foundKey->update($request->all());
|
||||
|
||||
return response()->json(serializeApiResponse([
|
||||
@@ -406,6 +409,7 @@ class SecurityController extends Controller
|
||||
if (is_null($key)) {
|
||||
return response()->json(['message' => 'Private Key not found.'], 404);
|
||||
}
|
||||
$this->authorize('delete', $key);
|
||||
|
||||
if ($key->isInUse()) {
|
||||
return response()->json([
|
||||
|
||||
@@ -144,6 +144,7 @@ class ServersController extends Controller
|
||||
if (is_null($server)) {
|
||||
return response()->json(['message' => 'Server not found.'], 404);
|
||||
}
|
||||
$this->authorize('view', $server);
|
||||
if ($with_resources) {
|
||||
$server['resources'] = $server->definedResources()->map(function ($resource) {
|
||||
$payload = [
|
||||
@@ -464,6 +465,7 @@ class ServersController extends Controller
|
||||
if (is_null($teamId)) {
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
$this->authorize('create', [ModelsServer::class]);
|
||||
|
||||
$return = validateIncomingRequest($request);
|
||||
if ($return instanceof \Illuminate\Http\JsonResponse) {
|
||||
@@ -664,6 +666,7 @@ class ServersController extends Controller
|
||||
if (! $server) {
|
||||
return response()->json(['message' => 'Server not found.'], 404);
|
||||
}
|
||||
$this->authorize('update', $server);
|
||||
if ($request->proxy_type) {
|
||||
$validProxyTypes = collect(ProxyTypes::cases())->map(function ($proxyType) {
|
||||
return str($proxyType->value)->lower();
|
||||
@@ -757,6 +760,7 @@ class ServersController extends Controller
|
||||
if (! $server) {
|
||||
return response()->json(['message' => 'Server not found.'], 404);
|
||||
}
|
||||
$this->authorize('delete', $server);
|
||||
if ($server->definedResources()->count() > 0) {
|
||||
return response()->json(['message' => 'Server has resources, so you need to delete them before.'], 400);
|
||||
}
|
||||
@@ -835,6 +839,7 @@ class ServersController extends Controller
|
||||
if (! $server) {
|
||||
return response()->json(['message' => 'Server not found.'], 404);
|
||||
}
|
||||
$this->authorize('update', $server);
|
||||
ValidateServer::dispatch($server);
|
||||
|
||||
return response()->json(['message' => 'Validation started.'], 201);
|
||||
|
||||
@@ -118,6 +118,7 @@ class TeamController extends Controller
|
||||
if (is_null($team)) {
|
||||
return response()->json(['message' => 'Team not found.'], 404);
|
||||
}
|
||||
$this->authorize('view', $team);
|
||||
$team = $this->removeSensitiveData($team);
|
||||
|
||||
return response()->json(
|
||||
@@ -176,6 +177,7 @@ class TeamController extends Controller
|
||||
if (is_null($team)) {
|
||||
return response()->json(['message' => 'Team not found.'], 404);
|
||||
}
|
||||
$this->authorize('view', $team);
|
||||
$members = $team->members;
|
||||
$members->makeHidden([
|
||||
'pivot',
|
||||
|
||||
@@ -65,58 +65,66 @@ class Heading extends Component
|
||||
|
||||
public function force_deploy_without_cache()
|
||||
{
|
||||
$this->authorize('deploy', $this->application);
|
||||
try {
|
||||
$this->authorize('deploy', $this->application);
|
||||
|
||||
$this->deploy(force_rebuild: true);
|
||||
$this->deploy(force_rebuild: true);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function deploy(bool $force_rebuild = false)
|
||||
{
|
||||
$this->authorize('deploy', $this->application);
|
||||
try {
|
||||
$this->authorize('deploy', $this->application);
|
||||
|
||||
if ($this->application->build_pack === 'dockercompose' && is_null($this->application->docker_compose_raw)) {
|
||||
$this->dispatch('error', 'Failed to deploy', 'Please load a Compose file first.');
|
||||
if ($this->application->build_pack === 'dockercompose' && is_null($this->application->docker_compose_raw)) {
|
||||
$this->dispatch('error', 'Failed to deploy', 'Please load a Compose file first.');
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
if ($this->application->destination->server->isSwarm() && str($this->application->docker_registry_image_name)->isEmpty()) {
|
||||
$this->dispatch('error', 'Failed to deploy.', 'To deploy to a Swarm cluster you must set a Docker image name first.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (data_get($this->application, 'settings.is_build_server_enabled') && str($this->application->docker_registry_image_name)->isEmpty()) {
|
||||
$this->dispatch('error', 'Failed to deploy.', 'To use a build server, you must first set a Docker image.<br>More information here: <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/build-server">documentation</a>');
|
||||
|
||||
return;
|
||||
}
|
||||
if ($this->application->additional_servers->count() > 0 && str($this->application->docker_registry_image_name)->isEmpty()) {
|
||||
$this->dispatch('error', 'Failed to deploy.', 'Before deploying to multiple servers, you must first set a Docker image in the General tab.<br>More information here: <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/multiple-servers">documentation</a>');
|
||||
|
||||
return;
|
||||
}
|
||||
$this->setDeploymentUuid();
|
||||
$result = queue_application_deployment(
|
||||
application: $this->application,
|
||||
deployment_uuid: $this->deploymentUuid,
|
||||
force_rebuild: $force_rebuild,
|
||||
);
|
||||
if ($result['status'] === 'queue_full') {
|
||||
$this->dispatch('error', 'Deployment queue full', $result['message']);
|
||||
|
||||
return;
|
||||
}
|
||||
if ($result['status'] === 'skipped') {
|
||||
$this->dispatch('error', 'Deployment skipped', $result['message']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return $this->redirectRoute('project.application.deployment.show', [
|
||||
'project_uuid' => $this->parameters['project_uuid'],
|
||||
'application_uuid' => $this->parameters['application_uuid'],
|
||||
'deployment_uuid' => $this->deploymentUuid,
|
||||
'environment_uuid' => $this->parameters['environment_uuid'],
|
||||
], navigate: false);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
if ($this->application->destination->server->isSwarm() && str($this->application->docker_registry_image_name)->isEmpty()) {
|
||||
$this->dispatch('error', 'Failed to deploy.', 'To deploy to a Swarm cluster you must set a Docker image name first.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (data_get($this->application, 'settings.is_build_server_enabled') && str($this->application->docker_registry_image_name)->isEmpty()) {
|
||||
$this->dispatch('error', 'Failed to deploy.', 'To use a build server, you must first set a Docker image.<br>More information here: <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/build-server">documentation</a>');
|
||||
|
||||
return;
|
||||
}
|
||||
if ($this->application->additional_servers->count() > 0 && str($this->application->docker_registry_image_name)->isEmpty()) {
|
||||
$this->dispatch('error', 'Failed to deploy.', 'Before deploying to multiple servers, you must first set a Docker image in the General tab.<br>More information here: <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/multiple-servers">documentation</a>');
|
||||
|
||||
return;
|
||||
}
|
||||
$this->setDeploymentUuid();
|
||||
$result = queue_application_deployment(
|
||||
application: $this->application,
|
||||
deployment_uuid: $this->deploymentUuid,
|
||||
force_rebuild: $force_rebuild,
|
||||
);
|
||||
if ($result['status'] === 'queue_full') {
|
||||
$this->dispatch('error', 'Deployment queue full', $result['message']);
|
||||
|
||||
return;
|
||||
}
|
||||
if ($result['status'] === 'skipped') {
|
||||
$this->dispatch('error', 'Deployment skipped', $result['message']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return $this->redirectRoute('project.application.deployment.show', [
|
||||
'project_uuid' => $this->parameters['project_uuid'],
|
||||
'application_uuid' => $this->parameters['application_uuid'],
|
||||
'deployment_uuid' => $this->deploymentUuid,
|
||||
'environment_uuid' => $this->parameters['environment_uuid'],
|
||||
], navigate: false);
|
||||
}
|
||||
|
||||
protected function setDeploymentUuid()
|
||||
@@ -127,45 +135,53 @@ class Heading extends Component
|
||||
|
||||
public function stop()
|
||||
{
|
||||
$this->authorize('deploy', $this->application);
|
||||
try {
|
||||
$this->authorize('deploy', $this->application);
|
||||
|
||||
$this->dispatch('info', 'Gracefully stopping application.<br/>It could take a while depending on the application.');
|
||||
StopApplication::dispatch($this->application, false, $this->docker_cleanup);
|
||||
$this->dispatch('info', 'Gracefully stopping application.<br/>It could take a while depending on the application.');
|
||||
StopApplication::dispatch($this->application, false, $this->docker_cleanup);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function restart()
|
||||
{
|
||||
$this->authorize('deploy', $this->application);
|
||||
try {
|
||||
$this->authorize('deploy', $this->application);
|
||||
|
||||
if ($this->application->additional_servers->count() > 0 && str($this->application->docker_registry_image_name)->isEmpty()) {
|
||||
$this->dispatch('error', 'Failed to deploy', 'Before deploying to multiple servers, you must first set a Docker image in the General tab.<br>More information here: <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/multiple-servers">documentation</a>');
|
||||
if ($this->application->additional_servers->count() > 0 && str($this->application->docker_registry_image_name)->isEmpty()) {
|
||||
$this->dispatch('error', 'Failed to deploy', 'Before deploying to multiple servers, you must first set a Docker image in the General tab.<br>More information here: <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/multiple-servers">documentation</a>');
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->setDeploymentUuid();
|
||||
$result = queue_application_deployment(
|
||||
application: $this->application,
|
||||
deployment_uuid: $this->deploymentUuid,
|
||||
restart_only: true,
|
||||
);
|
||||
if ($result['status'] === 'queue_full') {
|
||||
$this->dispatch('error', 'Deployment queue full', $result['message']);
|
||||
|
||||
return;
|
||||
}
|
||||
if ($result['status'] === 'skipped') {
|
||||
$this->dispatch('success', 'Deployment skipped', $result['message']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return $this->redirectRoute('project.application.deployment.show', [
|
||||
'project_uuid' => $this->parameters['project_uuid'],
|
||||
'application_uuid' => $this->parameters['application_uuid'],
|
||||
'deployment_uuid' => $this->deploymentUuid,
|
||||
'environment_uuid' => $this->parameters['environment_uuid'],
|
||||
], navigate: false);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
$this->setDeploymentUuid();
|
||||
$result = queue_application_deployment(
|
||||
application: $this->application,
|
||||
deployment_uuid: $this->deploymentUuid,
|
||||
restart_only: true,
|
||||
);
|
||||
if ($result['status'] === 'queue_full') {
|
||||
$this->dispatch('error', 'Deployment queue full', $result['message']);
|
||||
|
||||
return;
|
||||
}
|
||||
if ($result['status'] === 'skipped') {
|
||||
$this->dispatch('success', 'Deployment skipped', $result['message']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return $this->redirectRoute('project.application.deployment.show', [
|
||||
'project_uuid' => $this->parameters['project_uuid'],
|
||||
'application_uuid' => $this->parameters['application_uuid'],
|
||||
'deployment_uuid' => $this->deploymentUuid,
|
||||
'environment_uuid' => $this->parameters['environment_uuid'],
|
||||
], navigate: false);
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
||||
@@ -215,24 +215,31 @@ class Previews extends Component
|
||||
|
||||
public function force_deploy_without_cache(int $pull_request_id, ?string $pull_request_html_url = null)
|
||||
{
|
||||
$this->authorize('deploy', $this->application);
|
||||
try {
|
||||
$this->authorize('deploy', $this->application);
|
||||
|
||||
$this->deploy($pull_request_id, $pull_request_html_url, force_rebuild: true);
|
||||
$this->deploy($pull_request_id, $pull_request_html_url, force_rebuild: true);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function add_and_deploy(int $pull_request_id, ?string $pull_request_html_url = null)
|
||||
{
|
||||
$this->authorize('deploy', $this->application);
|
||||
try {
|
||||
$this->authorize('deploy', $this->application);
|
||||
|
||||
$this->add($pull_request_id, $pull_request_html_url);
|
||||
$this->deploy($pull_request_id, $pull_request_html_url);
|
||||
$this->add($pull_request_id, $pull_request_html_url);
|
||||
$this->deploy($pull_request_id, $pull_request_html_url);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function deploy(int $pull_request_id, ?string $pull_request_html_url = null, bool $force_rebuild = false)
|
||||
{
|
||||
$this->authorize('deploy', $this->application);
|
||||
|
||||
try {
|
||||
$this->authorize('deploy', $this->application);
|
||||
$this->setDeploymentUuid();
|
||||
$found = ApplicationPreview::where('application_id', $this->application->id)->where('pull_request_id', $pull_request_id)->first();
|
||||
if (! $found && ! is_null($pull_request_html_url)) {
|
||||
@@ -291,9 +298,8 @@ class Previews extends Component
|
||||
|
||||
public function stop(int $pull_request_id)
|
||||
{
|
||||
$this->authorize('deploy', $this->application);
|
||||
|
||||
try {
|
||||
$this->authorize('deploy', $this->application);
|
||||
$server = $this->application->destination->server;
|
||||
|
||||
if ($this->application->destination->server->isSwarm()) {
|
||||
|
||||
@@ -14,9 +14,13 @@ class BackupNow extends Component
|
||||
|
||||
public function backupNow()
|
||||
{
|
||||
$this->authorize('manageBackups', $this->backup->database);
|
||||
try {
|
||||
$this->authorize('manageBackups', $this->backup->database);
|
||||
|
||||
DatabaseBackupJob::dispatch($this->backup);
|
||||
$this->dispatch('success', 'Backup queued. It will be available in a few minutes.');
|
||||
DatabaseBackupJob::dispatch($this->backup);
|
||||
$this->dispatch('success', 'Backup queued. It will be available in a few minutes.');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,18 +86,26 @@ class Heading extends Component
|
||||
|
||||
public function restart()
|
||||
{
|
||||
$this->authorize('manage', $this->database);
|
||||
try {
|
||||
$this->authorize('manage', $this->database);
|
||||
|
||||
$activity = RestartDatabase::run($this->database);
|
||||
$this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class);
|
||||
$activity = RestartDatabase::run($this->database);
|
||||
$this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function start()
|
||||
{
|
||||
$this->authorize('manage', $this->database);
|
||||
try {
|
||||
$this->authorize('manage', $this->database);
|
||||
|
||||
$activity = StartDatabase::run($this->database);
|
||||
$this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class);
|
||||
$activity = StartDatabase::run($this->database);
|
||||
$this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
||||
@@ -56,22 +56,30 @@ class ScheduledBackups extends Component
|
||||
|
||||
public function setCustomType()
|
||||
{
|
||||
$this->authorize('update', $this->database);
|
||||
try {
|
||||
$this->authorize('update', $this->database);
|
||||
|
||||
$this->database->custom_type = $this->custom_type;
|
||||
$this->database->save();
|
||||
$this->dispatch('success', 'Database type set.');
|
||||
$this->refreshScheduledBackups();
|
||||
$this->database->custom_type = $this->custom_type;
|
||||
$this->database->save();
|
||||
$this->dispatch('success', 'Database type set.');
|
||||
$this->refreshScheduledBackups();
|
||||
} catch (\Throwable $e) {
|
||||
handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function delete($scheduled_backup_id): void
|
||||
{
|
||||
$backup = $this->database->scheduledBackups->find($scheduled_backup_id);
|
||||
$this->authorize('manageBackups', $this->database);
|
||||
try {
|
||||
$this->authorize('manageBackups', $this->database);
|
||||
|
||||
$backup->delete();
|
||||
$this->dispatch('success', 'Scheduled backup deleted.');
|
||||
$this->refreshScheduledBackups();
|
||||
$backup = $this->database->scheduledBackups->find($scheduled_backup_id);
|
||||
$backup->delete();
|
||||
$this->dispatch('success', 'Scheduled backup deleted.');
|
||||
$this->refreshScheduledBackups();
|
||||
} catch (\Throwable $e) {
|
||||
handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function refreshScheduledBackups(?int $id = null): void
|
||||
|
||||
@@ -30,18 +30,22 @@ class DeleteEnvironment extends Component
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$this->validate([
|
||||
'environment_id' => 'required|int',
|
||||
]);
|
||||
$environment = Environment::findOrFail($this->environment_id);
|
||||
$this->authorize('delete', $environment);
|
||||
try {
|
||||
$this->validate([
|
||||
'environment_id' => 'required|int',
|
||||
]);
|
||||
$environment = Environment::findOrFail($this->environment_id);
|
||||
$this->authorize('delete', $environment);
|
||||
|
||||
if ($environment->isEmpty()) {
|
||||
$environment->delete();
|
||||
if ($environment->isEmpty()) {
|
||||
$environment->delete();
|
||||
|
||||
return redirectRoute($this, 'project.show', ['project_uuid' => $this->parameters['project_uuid']]);
|
||||
return redirectRoute($this, 'project.show', ['project_uuid' => $this->parameters['project_uuid']]);
|
||||
}
|
||||
|
||||
return $this->dispatch('error', "<strong>Environment {$environment->name}</strong> has defined resources, please delete them first.");
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
return $this->dispatch('error', "<strong>Environment {$environment->name}</strong> has defined resources, please delete them first.");
|
||||
}
|
||||
}
|
||||
@@ -26,18 +26,22 @@ class DeleteProject extends Component
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$this->validate([
|
||||
'project_id' => 'required|int',
|
||||
]);
|
||||
$project = Project::findOrFail($this->project_id);
|
||||
$this->authorize('delete', $project);
|
||||
try {
|
||||
$this->validate([
|
||||
'project_id' => 'required|int',
|
||||
]);
|
||||
$project = Project::findOrFail($this->project_id);
|
||||
$this->authorize('delete', $project);
|
||||
|
||||
if ($project->isEmpty()) {
|
||||
$project->delete();
|
||||
if ($project->isEmpty()) {
|
||||
$project->delete();
|
||||
|
||||
return redirectRoute($this, 'project.index');
|
||||
return redirectRoute($this, 'project.index');
|
||||
}
|
||||
|
||||
return $this->dispatch('error', "<strong>Project {$project->name}</strong> has resources defined, please delete them first.");
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
return $this->dispatch('error', "<strong>Project {$project->name}</strong> has resources defined, please delete them first.");
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,15 @@ use App\Actions\Service\StartService;
|
||||
use App\Actions\Service\StopService;
|
||||
use App\Enums\ProcessStatus;
|
||||
use App\Models\Service;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Livewire\Component;
|
||||
use Spatie\Activitylog\Models\Activity;
|
||||
|
||||
class Heading extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public Service $service;
|
||||
|
||||
public array $parameters;
|
||||
@@ -99,13 +102,19 @@ class Heading extends Component
|
||||
|
||||
public function start()
|
||||
{
|
||||
$activity = StartService::run($this->service, pullLatestImages: true);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
try {
|
||||
$this->authorize('deploy', $this->service);
|
||||
$activity = StartService::run($this->service, pullLatestImages: true);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function forceDeploy()
|
||||
{
|
||||
try {
|
||||
$this->authorize('deploy', $this->service);
|
||||
$activities = Activity::where('properties->type_uuid', $this->service->uuid)
|
||||
->where(function ($q) {
|
||||
$q->where('properties->status', ProcessStatus::IN_PROGRESS->value)
|
||||
@@ -117,42 +126,53 @@ class Heading extends Component
|
||||
}
|
||||
$activity = StartService::run($this->service, pullLatestImages: true, stopBeforeStart: true);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
} catch (\Exception $e) {
|
||||
$this->dispatch('error', $e->getMessage());
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function stop()
|
||||
{
|
||||
try {
|
||||
$this->authorize('stop', $this->service);
|
||||
StopService::dispatch($this->service, false, $this->docker_cleanup);
|
||||
} catch (\Exception $e) {
|
||||
$this->dispatch('error', $e->getMessage());
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function restart()
|
||||
{
|
||||
$this->checkDeployments();
|
||||
if ($this->isDeploymentProgress) {
|
||||
$this->dispatch('error', 'There is a deployment in progress.');
|
||||
try {
|
||||
$this->authorize('deploy', $this->service);
|
||||
$this->checkDeployments();
|
||||
if ($this->isDeploymentProgress) {
|
||||
$this->dispatch('error', 'There is a deployment in progress.');
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
$activity = StartService::run($this->service, stopBeforeStart: true);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
$activity = StartService::run($this->service, stopBeforeStart: true);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
}
|
||||
|
||||
public function pullAndRestartEvent()
|
||||
{
|
||||
$this->checkDeployments();
|
||||
if ($this->isDeploymentProgress) {
|
||||
$this->dispatch('error', 'There is a deployment in progress.');
|
||||
try {
|
||||
$this->authorize('deploy', $this->service);
|
||||
$this->checkDeployments();
|
||||
if ($this->isDeploymentProgress) {
|
||||
$this->dispatch('error', 'There is a deployment in progress.');
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
$activity = StartService::run($this->service, pullLatestImages: true, stopBeforeStart: true);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
$activity = StartService::run($this->service, pullLatestImages: true, stopBeforeStart: true);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
||||
@@ -7,12 +7,15 @@ use App\Actions\Docker\GetContainersStatus;
|
||||
use App\Events\ApplicationStatusChanged;
|
||||
use App\Models\Server;
|
||||
use App\Models\StandaloneDocker;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Collection;
|
||||
use Livewire\Component;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
class Destination extends Component
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
|
||||
public $resource;
|
||||
|
||||
public Collection $networks;
|
||||
@@ -59,6 +62,7 @@ class Destination extends Component
|
||||
public function stop($serverId)
|
||||
{
|
||||
try {
|
||||
$this->authorize('deploy', $this->resource);
|
||||
$server = Server::ownedByCurrentTeam()->findOrFail($serverId);
|
||||
StopApplicationOneServer::run($this->resource, $server);
|
||||
$this->refreshServers();
|
||||
@@ -70,6 +74,7 @@ class Destination extends Component
|
||||
public function redeploy(int $network_id, int $server_id)
|
||||
{
|
||||
try {
|
||||
$this->authorize('deploy', $this->resource);
|
||||
if ($this->resource->additional_servers->count() > 0 && str($this->resource->docker_registry_image_name)->isEmpty()) {
|
||||
$this->dispatch('error', 'Failed to deploy.', 'Before deploying to multiple servers, you must first set a Docker image in the General tab.<br>More information here: <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/multiple-servers">documentation</a>');
|
||||
|
||||
@@ -110,15 +115,20 @@ class Destination extends Component
|
||||
|
||||
public function promote(int $network_id, int $server_id)
|
||||
{
|
||||
$main_destination = $this->resource->destination;
|
||||
$this->resource->update([
|
||||
'destination_id' => $network_id,
|
||||
'destination_type' => StandaloneDocker::class,
|
||||
]);
|
||||
$this->resource->additional_networks()->detach($network_id, ['server_id' => $server_id]);
|
||||
$this->resource->additional_networks()->attach($main_destination->id, ['server_id' => $main_destination->server->id]);
|
||||
$this->refreshServers();
|
||||
$this->resource->refresh();
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
$main_destination = $this->resource->destination;
|
||||
$this->resource->update([
|
||||
'destination_id' => $network_id,
|
||||
'destination_type' => StandaloneDocker::class,
|
||||
]);
|
||||
$this->resource->additional_networks()->detach($network_id, ['server_id' => $server_id]);
|
||||
$this->resource->additional_networks()->attach($main_destination->id, ['server_id' => $main_destination->server->id]);
|
||||
$this->refreshServers();
|
||||
$this->resource->refresh();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function refreshServers()
|
||||
@@ -130,13 +140,19 @@ class Destination extends Component
|
||||
|
||||
public function addServer(int $network_id, int $server_id)
|
||||
{
|
||||
$this->resource->additional_networks()->attach($network_id, ['server_id' => $server_id]);
|
||||
$this->dispatch('refresh');
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
$this->resource->additional_networks()->attach($network_id, ['server_id' => $server_id]);
|
||||
$this->dispatch('refresh');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function removeServer(int $network_id, int $server_id, $password)
|
||||
{
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
if (! verifyPasswordConfirmation($password, $this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -70,8 +70,12 @@ class HealthChecks extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->authorize('view', $this->resource);
|
||||
$this->syncData();
|
||||
try {
|
||||
$this->authorize('view', $this->resource);
|
||||
$this->syncData();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function syncData(bool $toModel = false): void
|
||||
|
||||
@@ -47,224 +47,87 @@ class ResourceOperations extends Component
|
||||
|
||||
public function cloneTo($destination_id)
|
||||
{
|
||||
$this->authorize('update', $this->resource);
|
||||
try {
|
||||
$this->authorize('update', $this->resource);
|
||||
|
||||
$teamScope = fn ($q) => $q->where('team_id', currentTeam()->id);
|
||||
$new_destination = StandaloneDocker::whereHas('server', $teamScope)->find($destination_id);
|
||||
if (! $new_destination) {
|
||||
$new_destination = SwarmDocker::whereHas('server', $teamScope)->find($destination_id);
|
||||
}
|
||||
if (! $new_destination) {
|
||||
return $this->addError('destination_id', 'Destination not found.');
|
||||
}
|
||||
$uuid = (string) new Cuid2;
|
||||
$server = $new_destination->server;
|
||||
|
||||
if ($this->resource->getMorphClass() === \App\Models\Application::class) {
|
||||
$new_resource = clone_application($this->resource, $new_destination, ['uuid' => $uuid], $this->cloneVolumeData);
|
||||
|
||||
$route = route('project.application.configuration', [
|
||||
'project_uuid' => $this->projectUuid,
|
||||
'environment_uuid' => $this->environmentUuid,
|
||||
'application_uuid' => $new_resource->uuid,
|
||||
]).'#resource-operations';
|
||||
|
||||
return redirect()->to($route);
|
||||
} elseif (
|
||||
$this->resource->getMorphClass() === \App\Models\StandalonePostgresql::class ||
|
||||
$this->resource->getMorphClass() === \App\Models\StandaloneMongodb::class ||
|
||||
$this->resource->getMorphClass() === \App\Models\StandaloneMysql::class ||
|
||||
$this->resource->getMorphClass() === \App\Models\StandaloneMariadb::class ||
|
||||
$this->resource->getMorphClass() === \App\Models\StandaloneRedis::class ||
|
||||
$this->resource->getMorphClass() === \App\Models\StandaloneKeydb::class ||
|
||||
$this->resource->getMorphClass() === \App\Models\StandaloneDragonfly::class ||
|
||||
$this->resource->getMorphClass() === \App\Models\StandaloneClickhouse::class
|
||||
) {
|
||||
$teamScope = fn ($q) => $q->where('team_id', currentTeam()->id);
|
||||
$new_destination = StandaloneDocker::whereHas('server', $teamScope)->find($destination_id);
|
||||
if (! $new_destination) {
|
||||
$new_destination = SwarmDocker::whereHas('server', $teamScope)->find($destination_id);
|
||||
}
|
||||
if (! $new_destination) {
|
||||
return $this->addError('destination_id', 'Destination not found.');
|
||||
}
|
||||
$uuid = (string) new Cuid2;
|
||||
$new_resource = $this->resource->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'uuid' => $uuid,
|
||||
'name' => $this->resource->name.'-clone-'.$uuid,
|
||||
'status' => 'exited',
|
||||
'started_at' => null,
|
||||
'destination_id' => $new_destination->id,
|
||||
]);
|
||||
$new_resource->save();
|
||||
$server = $new_destination->server;
|
||||
|
||||
$tags = $this->resource->tags;
|
||||
foreach ($tags as $tag) {
|
||||
$new_resource->tags()->attach($tag->id);
|
||||
}
|
||||
if ($this->resource->getMorphClass() === \App\Models\Application::class) {
|
||||
$new_resource = clone_application($this->resource, $new_destination, ['uuid' => $uuid], $this->cloneVolumeData);
|
||||
|
||||
$new_resource->persistentStorages()->delete();
|
||||
$persistentVolumes = $this->resource->persistentStorages()->get();
|
||||
foreach ($persistentVolumes as $volume) {
|
||||
$originalName = $volume->name;
|
||||
$newName = '';
|
||||
$route = route('project.application.configuration', [
|
||||
'project_uuid' => $this->projectUuid,
|
||||
'environment_uuid' => $this->environmentUuid,
|
||||
'application_uuid' => $new_resource->uuid,
|
||||
]).'#resource-operations';
|
||||
|
||||
if (str_starts_with($originalName, 'postgres-data-')) {
|
||||
$newName = 'postgres-data-'.$new_resource->uuid;
|
||||
} elseif (str_starts_with($originalName, 'mysql-data-')) {
|
||||
$newName = 'mysql-data-'.$new_resource->uuid;
|
||||
} elseif (str_starts_with($originalName, 'redis-data-')) {
|
||||
$newName = 'redis-data-'.$new_resource->uuid;
|
||||
} elseif (str_starts_with($originalName, 'clickhouse-data-')) {
|
||||
$newName = 'clickhouse-data-'.$new_resource->uuid;
|
||||
} elseif (str_starts_with($originalName, 'mariadb-data-')) {
|
||||
$newName = 'mariadb-data-'.$new_resource->uuid;
|
||||
} elseif (str_starts_with($originalName, 'mongodb-data-')) {
|
||||
$newName = 'mongodb-data-'.$new_resource->uuid;
|
||||
} elseif (str_starts_with($originalName, 'keydb-data-')) {
|
||||
$newName = 'keydb-data-'.$new_resource->uuid;
|
||||
} elseif (str_starts_with($originalName, 'dragonfly-data-')) {
|
||||
$newName = 'dragonfly-data-'.$new_resource->uuid;
|
||||
} else {
|
||||
if (str_starts_with($volume->name, $this->resource->uuid)) {
|
||||
$newName = str($volume->name)->replace($this->resource->uuid, $new_resource->uuid);
|
||||
} else {
|
||||
$newName = $new_resource->uuid.'-'.$volume->name;
|
||||
}
|
||||
}
|
||||
|
||||
$newPersistentVolume = $volume->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'name' => $newName,
|
||||
'resource_id' => $new_resource->id,
|
||||
]);
|
||||
$newPersistentVolume->save();
|
||||
|
||||
if ($this->cloneVolumeData) {
|
||||
try {
|
||||
StopDatabase::dispatch($this->resource);
|
||||
$sourceVolume = $volume->name;
|
||||
$targetVolume = $newPersistentVolume->name;
|
||||
$sourceServer = $this->resource->destination->server;
|
||||
$targetServer = $new_resource->destination->server;
|
||||
|
||||
VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume);
|
||||
|
||||
StartDatabase::dispatch($this->resource);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$fileStorages = $this->resource->fileStorages()->get();
|
||||
foreach ($fileStorages as $storage) {
|
||||
$newStorage = $storage->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'resource_id' => $new_resource->id,
|
||||
]);
|
||||
$newStorage->save();
|
||||
}
|
||||
|
||||
$scheduledBackups = $this->resource->scheduledBackups()->get();
|
||||
foreach ($scheduledBackups as $backup) {
|
||||
return redirect()->to($route);
|
||||
} elseif (
|
||||
$this->resource->getMorphClass() === \App\Models\StandalonePostgresql::class ||
|
||||
$this->resource->getMorphClass() === \App\Models\StandaloneMongodb::class ||
|
||||
$this->resource->getMorphClass() === \App\Models\StandaloneMysql::class ||
|
||||
$this->resource->getMorphClass() === \App\Models\StandaloneMariadb::class ||
|
||||
$this->resource->getMorphClass() === \App\Models\StandaloneRedis::class ||
|
||||
$this->resource->getMorphClass() === \App\Models\StandaloneKeydb::class ||
|
||||
$this->resource->getMorphClass() === \App\Models\StandaloneDragonfly::class ||
|
||||
$this->resource->getMorphClass() === \App\Models\StandaloneClickhouse::class
|
||||
) {
|
||||
$uuid = (string) new Cuid2;
|
||||
$newBackup = $backup->replicate([
|
||||
$new_resource = $this->resource->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'uuid' => $uuid,
|
||||
'database_id' => $new_resource->id,
|
||||
'database_type' => $new_resource->getMorphClass(),
|
||||
'team_id' => currentTeam()->id,
|
||||
]);
|
||||
$newBackup->save();
|
||||
}
|
||||
|
||||
$environmentVaribles = $this->resource->environment_variables()->get();
|
||||
foreach ($environmentVaribles as $environmentVarible) {
|
||||
$payload = [
|
||||
'resourceable_id' => $new_resource->id,
|
||||
'resourceable_type' => $new_resource->getMorphClass(),
|
||||
];
|
||||
$newEnvironmentVariable = $environmentVarible->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill($payload);
|
||||
$newEnvironmentVariable->save();
|
||||
}
|
||||
|
||||
$route = route('project.database.configuration', [
|
||||
'project_uuid' => $this->projectUuid,
|
||||
'environment_uuid' => $this->environmentUuid,
|
||||
'database_uuid' => $new_resource->uuid,
|
||||
]).'#resource-operations';
|
||||
|
||||
return redirect()->to($route);
|
||||
} elseif ($this->resource->type() === 'service') {
|
||||
$uuid = (string) new Cuid2;
|
||||
$new_resource = $this->resource->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'uuid' => $uuid,
|
||||
'name' => $this->resource->name.'-clone-'.$uuid,
|
||||
'destination_id' => $new_destination->id,
|
||||
'destination_type' => $new_destination->getMorphClass(),
|
||||
'server_id' => $new_destination->server_id, // server_id is probably not needed anymore because of the new polymorphic relationships (here it is needed for clone to a different server to work - but maybe we can drop the column)
|
||||
]);
|
||||
|
||||
$new_resource->save();
|
||||
|
||||
$tags = $this->resource->tags;
|
||||
foreach ($tags as $tag) {
|
||||
$new_resource->tags()->attach($tag->id);
|
||||
}
|
||||
|
||||
$scheduledTasks = $this->resource->scheduled_tasks()->get();
|
||||
foreach ($scheduledTasks as $task) {
|
||||
$newTask = $task->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'uuid' => (string) new Cuid2,
|
||||
'service_id' => $new_resource->id,
|
||||
'team_id' => currentTeam()->id,
|
||||
]);
|
||||
$newTask->save();
|
||||
}
|
||||
|
||||
$environmentVariables = $this->resource->environment_variables()->get();
|
||||
foreach ($environmentVariables as $environmentVariable) {
|
||||
$newEnvironmentVariable = $environmentVariable->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'resourceable_id' => $new_resource->id,
|
||||
'resourceable_type' => $new_resource->getMorphClass(),
|
||||
]);
|
||||
$newEnvironmentVariable->save();
|
||||
}
|
||||
|
||||
foreach ($new_resource->applications() as $application) {
|
||||
$application->update([
|
||||
'name' => $this->resource->name.'-clone-'.$uuid,
|
||||
'status' => 'exited',
|
||||
'started_at' => null,
|
||||
'destination_id' => $new_destination->id,
|
||||
]);
|
||||
$new_resource->save();
|
||||
|
||||
$persistentVolumes = $application->persistentStorages()->get();
|
||||
$tags = $this->resource->tags;
|
||||
foreach ($tags as $tag) {
|
||||
$new_resource->tags()->attach($tag->id);
|
||||
}
|
||||
|
||||
$new_resource->persistentStorages()->delete();
|
||||
$persistentVolumes = $this->resource->persistentStorages()->get();
|
||||
foreach ($persistentVolumes as $volume) {
|
||||
$originalName = $volume->name;
|
||||
$newName = '';
|
||||
if (str_starts_with($volume->name, $volume->resource->uuid)) {
|
||||
$newName = str($volume->name)->replace($volume->resource->uuid, $application->uuid);
|
||||
|
||||
if (str_starts_with($originalName, 'postgres-data-')) {
|
||||
$newName = 'postgres-data-'.$new_resource->uuid;
|
||||
} elseif (str_starts_with($originalName, 'mysql-data-')) {
|
||||
$newName = 'mysql-data-'.$new_resource->uuid;
|
||||
} elseif (str_starts_with($originalName, 'redis-data-')) {
|
||||
$newName = 'redis-data-'.$new_resource->uuid;
|
||||
} elseif (str_starts_with($originalName, 'clickhouse-data-')) {
|
||||
$newName = 'clickhouse-data-'.$new_resource->uuid;
|
||||
} elseif (str_starts_with($originalName, 'mariadb-data-')) {
|
||||
$newName = 'mariadb-data-'.$new_resource->uuid;
|
||||
} elseif (str_starts_with($originalName, 'mongodb-data-')) {
|
||||
$newName = 'mongodb-data-'.$new_resource->uuid;
|
||||
} elseif (str_starts_with($originalName, 'keydb-data-')) {
|
||||
$newName = 'keydb-data-'.$new_resource->uuid;
|
||||
} elseif (str_starts_with($originalName, 'dragonfly-data-')) {
|
||||
$newName = 'dragonfly-data-'.$new_resource->uuid;
|
||||
} else {
|
||||
$newName = $application->uuid.'-'.str($volume->name)->afterLast('-');
|
||||
if (str_starts_with($volume->name, $this->resource->uuid)) {
|
||||
$newName = str($volume->name)->replace($this->resource->uuid, $new_resource->uuid);
|
||||
} else {
|
||||
$newName = $new_resource->uuid.'-'.$volume->name;
|
||||
}
|
||||
}
|
||||
|
||||
$newPersistentVolume = $volume->replicate([
|
||||
@@ -273,79 +136,220 @@ class ResourceOperations extends Component
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'name' => $newName,
|
||||
'resource_id' => $application->id,
|
||||
'resource_id' => $new_resource->id,
|
||||
]);
|
||||
$newPersistentVolume->save();
|
||||
|
||||
if ($this->cloneVolumeData) {
|
||||
try {
|
||||
StopService::dispatch($application);
|
||||
StopDatabase::dispatch($this->resource);
|
||||
$sourceVolume = $volume->name;
|
||||
$targetVolume = $newPersistentVolume->name;
|
||||
$sourceServer = $application->service->destination->server;
|
||||
$sourceServer = $this->resource->destination->server;
|
||||
$targetServer = $new_resource->destination->server;
|
||||
|
||||
VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume);
|
||||
|
||||
StartService::dispatch($application);
|
||||
StartDatabase::dispatch($this->resource);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($new_resource->databases() as $database) {
|
||||
$database->update([
|
||||
'status' => 'exited',
|
||||
]);
|
||||
|
||||
$persistentVolumes = $database->persistentStorages()->get();
|
||||
foreach ($persistentVolumes as $volume) {
|
||||
$newName = '';
|
||||
if (str_starts_with($volume->name, $volume->resource->uuid)) {
|
||||
$newName = str($volume->name)->replace($volume->resource->uuid, $database->uuid);
|
||||
} else {
|
||||
$newName = $database->uuid.'-'.str($volume->name)->afterLast('-');
|
||||
}
|
||||
|
||||
$newPersistentVolume = $volume->replicate([
|
||||
$fileStorages = $this->resource->fileStorages()->get();
|
||||
foreach ($fileStorages as $storage) {
|
||||
$newStorage = $storage->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'name' => $newName,
|
||||
'resource_id' => $database->id,
|
||||
'resource_id' => $new_resource->id,
|
||||
]);
|
||||
$newPersistentVolume->save();
|
||||
$newStorage->save();
|
||||
}
|
||||
|
||||
if ($this->cloneVolumeData) {
|
||||
try {
|
||||
StopService::dispatch($database->service);
|
||||
$sourceVolume = $volume->name;
|
||||
$targetVolume = $newPersistentVolume->name;
|
||||
$sourceServer = $database->service->destination->server;
|
||||
$targetServer = $new_resource->destination->server;
|
||||
$scheduledBackups = $this->resource->scheduledBackups()->get();
|
||||
foreach ($scheduledBackups as $backup) {
|
||||
$uuid = (string) new Cuid2;
|
||||
$newBackup = $backup->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'uuid' => $uuid,
|
||||
'database_id' => $new_resource->id,
|
||||
'database_type' => $new_resource->getMorphClass(),
|
||||
'team_id' => currentTeam()->id,
|
||||
]);
|
||||
$newBackup->save();
|
||||
}
|
||||
|
||||
VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume);
|
||||
$environmentVaribles = $this->resource->environment_variables()->get();
|
||||
foreach ($environmentVaribles as $environmentVarible) {
|
||||
$payload = [
|
||||
'resourceable_id' => $new_resource->id,
|
||||
'resourceable_type' => $new_resource->getMorphClass(),
|
||||
];
|
||||
$newEnvironmentVariable = $environmentVarible->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill($payload);
|
||||
$newEnvironmentVariable->save();
|
||||
}
|
||||
|
||||
StartService::dispatch($database->service);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage());
|
||||
$route = route('project.database.configuration', [
|
||||
'project_uuid' => $this->projectUuid,
|
||||
'environment_uuid' => $this->environmentUuid,
|
||||
'database_uuid' => $new_resource->uuid,
|
||||
]).'#resource-operations';
|
||||
|
||||
return redirect()->to($route);
|
||||
} elseif ($this->resource->type() === 'service') {
|
||||
$uuid = (string) new Cuid2;
|
||||
$new_resource = $this->resource->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'uuid' => $uuid,
|
||||
'name' => $this->resource->name.'-clone-'.$uuid,
|
||||
'destination_id' => $new_destination->id,
|
||||
'destination_type' => $new_destination->getMorphClass(),
|
||||
'server_id' => $new_destination->server_id, // server_id is probably not needed anymore because of the new polymorphic relationships (here it is needed for clone to a different server to work - but maybe we can drop the column)
|
||||
]);
|
||||
|
||||
$new_resource->save();
|
||||
|
||||
$tags = $this->resource->tags;
|
||||
foreach ($tags as $tag) {
|
||||
$new_resource->tags()->attach($tag->id);
|
||||
}
|
||||
|
||||
$scheduledTasks = $this->resource->scheduled_tasks()->get();
|
||||
foreach ($scheduledTasks as $task) {
|
||||
$newTask = $task->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'uuid' => (string) new Cuid2,
|
||||
'service_id' => $new_resource->id,
|
||||
'team_id' => currentTeam()->id,
|
||||
]);
|
||||
$newTask->save();
|
||||
}
|
||||
|
||||
$environmentVariables = $this->resource->environment_variables()->get();
|
||||
foreach ($environmentVariables as $environmentVariable) {
|
||||
$newEnvironmentVariable = $environmentVariable->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'resourceable_id' => $new_resource->id,
|
||||
'resourceable_type' => $new_resource->getMorphClass(),
|
||||
]);
|
||||
$newEnvironmentVariable->save();
|
||||
}
|
||||
|
||||
foreach ($new_resource->applications() as $application) {
|
||||
$application->update([
|
||||
'status' => 'exited',
|
||||
]);
|
||||
|
||||
$persistentVolumes = $application->persistentStorages()->get();
|
||||
foreach ($persistentVolumes as $volume) {
|
||||
$newName = '';
|
||||
if (str_starts_with($volume->name, $volume->resource->uuid)) {
|
||||
$newName = str($volume->name)->replace($volume->resource->uuid, $application->uuid);
|
||||
} else {
|
||||
$newName = $application->uuid.'-'.str($volume->name)->afterLast('-');
|
||||
}
|
||||
|
||||
$newPersistentVolume = $volume->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'name' => $newName,
|
||||
'resource_id' => $application->id,
|
||||
]);
|
||||
$newPersistentVolume->save();
|
||||
|
||||
if ($this->cloneVolumeData) {
|
||||
try {
|
||||
StopService::dispatch($application);
|
||||
$sourceVolume = $volume->name;
|
||||
$targetVolume = $newPersistentVolume->name;
|
||||
$sourceServer = $application->service->destination->server;
|
||||
$targetServer = $new_resource->destination->server;
|
||||
|
||||
VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume);
|
||||
|
||||
StartService::dispatch($application);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($new_resource->databases() as $database) {
|
||||
$database->update([
|
||||
'status' => 'exited',
|
||||
]);
|
||||
|
||||
$persistentVolumes = $database->persistentStorages()->get();
|
||||
foreach ($persistentVolumes as $volume) {
|
||||
$newName = '';
|
||||
if (str_starts_with($volume->name, $volume->resource->uuid)) {
|
||||
$newName = str($volume->name)->replace($volume->resource->uuid, $database->uuid);
|
||||
} else {
|
||||
$newName = $database->uuid.'-'.str($volume->name)->afterLast('-');
|
||||
}
|
||||
|
||||
$newPersistentVolume = $volume->replicate([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])->fill([
|
||||
'name' => $newName,
|
||||
'resource_id' => $database->id,
|
||||
]);
|
||||
$newPersistentVolume->save();
|
||||
|
||||
if ($this->cloneVolumeData) {
|
||||
try {
|
||||
StopService::dispatch($database->service);
|
||||
$sourceVolume = $volume->name;
|
||||
$targetVolume = $newPersistentVolume->name;
|
||||
$sourceServer = $database->service->destination->server;
|
||||
$targetServer = $new_resource->destination->server;
|
||||
|
||||
VolumeCloneJob::dispatch($sourceVolume, $targetVolume, $sourceServer, $targetServer, $newPersistentVolume);
|
||||
|
||||
StartService::dispatch($database->service);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('Failed to copy volume data for '.$volume->name.': '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$new_resource->parse();
|
||||
|
||||
$route = route('project.service.configuration', [
|
||||
'project_uuid' => $this->projectUuid,
|
||||
'environment_uuid' => $this->environmentUuid,
|
||||
'service_uuid' => $new_resource->uuid,
|
||||
]).'#resource-operations';
|
||||
|
||||
return redirect()->to($route);
|
||||
}
|
||||
|
||||
$new_resource->parse();
|
||||
|
||||
$route = route('project.service.configuration', [
|
||||
'project_uuid' => $this->projectUuid,
|
||||
'environment_uuid' => $this->environmentUuid,
|
||||
'service_uuid' => $new_resource->uuid,
|
||||
]).'#resource-operations';
|
||||
|
||||
return redirect()->to($route);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ class ApiTokens extends Component
|
||||
|
||||
public bool $canUseWritePermissions = false;
|
||||
|
||||
public bool $canUseDeployPermissions = false;
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.security.api-tokens');
|
||||
@@ -33,6 +35,7 @@ class ApiTokens extends Component
|
||||
$this->isApiEnabled = InstanceSettings::get()->is_api_enabled;
|
||||
$this->canUseRootPermissions = auth()->user()->can('useRootPermissions', PersonalAccessToken::class);
|
||||
$this->canUseWritePermissions = auth()->user()->can('useWritePermissions', PersonalAccessToken::class);
|
||||
$this->canUseDeployPermissions = auth()->user()->can('useDeployPermissions', PersonalAccessToken::class);
|
||||
$this->getTokens();
|
||||
}
|
||||
|
||||
@@ -60,6 +63,13 @@ class ApiTokens extends Component
|
||||
return;
|
||||
}
|
||||
|
||||
if ($permissionToUpdate == 'deploy' && ! $this->canUseDeployPermissions) {
|
||||
$this->dispatch('error', 'You do not have permission to use deploy permissions.');
|
||||
$this->permissions = array_diff($this->permissions, ['deploy']);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($permissionToUpdate == 'root') {
|
||||
$this->permissions = ['root'];
|
||||
} elseif ($permissionToUpdate == 'read:sensitive' && ! in_array('read', $this->permissions)) {
|
||||
@@ -88,6 +98,10 @@ class ApiTokens extends Component
|
||||
throw new \Exception('You do not have permission to create tokens with write permissions.');
|
||||
}
|
||||
|
||||
if (in_array('deploy', $this->permissions) && ! $this->canUseDeployPermissions) {
|
||||
throw new \Exception('You do not have permission to create tokens with deploy permissions.');
|
||||
}
|
||||
|
||||
$this->validate([
|
||||
'description' => 'required|min:3|max:255',
|
||||
]);
|
||||
|
||||
@@ -20,15 +20,19 @@ class CloudInitScriptForm extends Component
|
||||
|
||||
public function mount(?int $scriptId = null)
|
||||
{
|
||||
if ($scriptId) {
|
||||
$this->scriptId = $scriptId;
|
||||
$cloudInitScript = CloudInitScript::ownedByCurrentTeam()->findOrFail($scriptId);
|
||||
$this->authorize('update', $cloudInitScript);
|
||||
try {
|
||||
if ($scriptId) {
|
||||
$this->scriptId = $scriptId;
|
||||
$cloudInitScript = CloudInitScript::ownedByCurrentTeam()->findOrFail($scriptId);
|
||||
$this->authorize('update', $cloudInitScript);
|
||||
|
||||
$this->name = $cloudInitScript->name;
|
||||
$this->script = $cloudInitScript->script;
|
||||
} else {
|
||||
$this->authorize('create', CloudInitScript::class);
|
||||
$this->name = $cloudInitScript->name;
|
||||
$this->script = $cloudInitScript->script;
|
||||
} else {
|
||||
$this->authorize('create', CloudInitScript::class);
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,11 @@ class CloudProviderTokenForm extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->authorize('create', CloudProviderToken::class);
|
||||
try {
|
||||
$this->authorize('create', CloudProviderToken::class);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
protected function rules(): array
|
||||
|
||||
@@ -14,8 +14,12 @@ class CloudProviderTokens extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->authorize('viewAny', CloudProviderToken::class);
|
||||
$this->loadTokens();
|
||||
try {
|
||||
$this->authorize('viewAny', CloudProviderToken::class);
|
||||
$this->loadTokens();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function getListeners()
|
||||
|
||||
@@ -21,8 +21,12 @@ class Index extends Component
|
||||
|
||||
public function cleanupUnusedKeys()
|
||||
{
|
||||
$this->authorize('create', PrivateKey::class);
|
||||
PrivateKey::cleanupUnusedKeys();
|
||||
$this->dispatch('success', 'Unused keys have been cleaned up.');
|
||||
try {
|
||||
$this->authorize('create', PrivateKey::class);
|
||||
PrivateKey::cleanupUnusedKeys();
|
||||
$this->dispatch('success', 'Unused keys have been cleaned up.');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,14 +78,18 @@ class ByHetzner extends Component
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->authorize('viewAny', CloudProviderToken::class);
|
||||
$this->loadTokens();
|
||||
$this->loadSavedCloudInitScripts();
|
||||
$this->server_name = generate_random_name();
|
||||
$this->private_keys = PrivateKey::ownedAndOnlySShKeys()->where('id', '!=', 0)->get();
|
||||
try {
|
||||
$this->authorize('viewAny', CloudProviderToken::class);
|
||||
$this->loadTokens();
|
||||
$this->loadSavedCloudInitScripts();
|
||||
$this->server_name = generate_random_name();
|
||||
$this->private_keys = PrivateKey::ownedAndOnlySShKeys()->where('id', '!=', 0)->get();
|
||||
|
||||
if ($this->private_keys->count() > 0) {
|
||||
$this->private_key_id = $this->private_keys->first()->id;
|
||||
if ($this->private_keys->count() > 0) {
|
||||
$this->private_key_id = $this->private_keys->first()->id;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,11 +96,15 @@ class Proxy extends Component
|
||||
|
||||
public function changeProxy()
|
||||
{
|
||||
$this->authorize('update', $this->server);
|
||||
$this->server->proxy = null;
|
||||
$this->server->save();
|
||||
try {
|
||||
$this->authorize('update', $this->server);
|
||||
$this->server->proxy = null;
|
||||
$this->server->save();
|
||||
|
||||
$this->dispatch('reloadWindow');
|
||||
$this->dispatch('reloadWindow');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function selectProxy($proxy_type)
|
||||
|
||||
@@ -22,34 +22,38 @@ class DynamicConfigurationNavbar extends Component
|
||||
|
||||
public function delete(string $fileName)
|
||||
{
|
||||
$this->authorize('update', $this->server);
|
||||
$proxy_path = $this->server->proxyPath();
|
||||
$proxy_type = $this->server->proxyType();
|
||||
try {
|
||||
$this->authorize('update', $this->server);
|
||||
$proxy_path = $this->server->proxyPath();
|
||||
$proxy_type = $this->server->proxyType();
|
||||
|
||||
// Decode filename: pipes are used to encode dots for Livewire property binding
|
||||
// (e.g., 'my|service.yaml' -> 'my.service.yaml')
|
||||
// This must happen BEFORE validation because validateShellSafePath() correctly
|
||||
// rejects pipe characters as dangerous shell metacharacters
|
||||
$file = str_replace('|', '.', $fileName);
|
||||
// Decode filename: pipes are used to encode dots for Livewire property binding
|
||||
// (e.g., 'my|service.yaml' -> 'my.service.yaml')
|
||||
// This must happen BEFORE validation because validateShellSafePath() correctly
|
||||
// rejects pipe characters as dangerous shell metacharacters
|
||||
$file = str_replace('|', '.', $fileName);
|
||||
|
||||
// Validate filename to prevent command injection
|
||||
validateShellSafePath($file, 'proxy configuration filename');
|
||||
// Validate filename to prevent command injection
|
||||
validateShellSafePath($file, 'proxy configuration filename');
|
||||
|
||||
if ($proxy_type === 'CADDY' && $file === 'Caddyfile') {
|
||||
$this->dispatch('error', 'Cannot delete Caddyfile.');
|
||||
if ($proxy_type === 'CADDY' && $file === 'Caddyfile') {
|
||||
$this->dispatch('error', 'Cannot delete Caddyfile.');
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
$fullPath = "{$proxy_path}/dynamic/{$file}";
|
||||
$escapedPath = escapeshellarg($fullPath);
|
||||
instant_remote_process(["rm -f {$escapedPath}"], $this->server);
|
||||
if ($proxy_type === 'CADDY') {
|
||||
$this->server->reloadCaddy();
|
||||
}
|
||||
$this->dispatch('success', 'File deleted.');
|
||||
$this->dispatch('loadDynamicConfigurations');
|
||||
$this->dispatch('refresh');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
$fullPath = "{$proxy_path}/dynamic/{$file}";
|
||||
$escapedPath = escapeshellarg($fullPath);
|
||||
instant_remote_process(["rm -f {$escapedPath}"], $this->server);
|
||||
if ($proxy_type === 'CADDY') {
|
||||
$this->server->reloadCaddy();
|
||||
}
|
||||
$this->dispatch('success', 'File deleted.');
|
||||
$this->dispatch('loadDynamicConfigurations');
|
||||
$this->dispatch('refresh');
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
||||
@@ -29,23 +29,38 @@ class Resources extends Component
|
||||
|
||||
public function startUnmanaged($id)
|
||||
{
|
||||
$this->server->startUnmanaged($id);
|
||||
$this->dispatch('success', 'Container started.');
|
||||
$this->loadUnmanagedContainers();
|
||||
try {
|
||||
$this->authorize('update', $this->server);
|
||||
$this->server->startUnmanaged($id);
|
||||
$this->dispatch('success', 'Container started.');
|
||||
$this->loadUnmanagedContainers();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function restartUnmanaged($id)
|
||||
{
|
||||
$this->server->restartUnmanaged($id);
|
||||
$this->dispatch('success', 'Container restarted.');
|
||||
$this->loadUnmanagedContainers();
|
||||
try {
|
||||
$this->authorize('update', $this->server);
|
||||
$this->server->restartUnmanaged($id);
|
||||
$this->dispatch('success', 'Container restarted.');
|
||||
$this->loadUnmanagedContainers();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function stopUnmanaged($id)
|
||||
{
|
||||
$this->server->stopUnmanaged($id);
|
||||
$this->dispatch('success', 'Container stopped.');
|
||||
$this->loadUnmanagedContainers();
|
||||
try {
|
||||
$this->authorize('update', $this->server);
|
||||
$this->server->stopUnmanaged($id);
|
||||
$this->dispatch('success', 'Container stopped.');
|
||||
$this->loadUnmanagedContainers();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function refreshStatus()
|
||||
|
||||
@@ -41,7 +41,11 @@ class Patches extends Component
|
||||
{
|
||||
$this->parameters = get_route_parameters();
|
||||
$this->server = Server::ownedByCurrentTeam()->whereUuid($this->parameters['server_uuid'])->firstOrFail();
|
||||
$this->authorize('viewSecurity', $this->server);
|
||||
try {
|
||||
$this->authorize('viewSecurity', $this->server);
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function checkForUpdatesDispatch()
|
||||
@@ -69,14 +73,14 @@ class Patches extends Component
|
||||
|
||||
public function updateAllPackages()
|
||||
{
|
||||
$this->authorize('update', $this->server);
|
||||
if (! $this->packageManager || ! $this->osId) {
|
||||
$this->dispatch('error', message: 'Run "Check for updates" first.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->authorize('update', $this->server);
|
||||
if (! $this->packageManager || ! $this->osId) {
|
||||
$this->dispatch('error', message: 'Run "Check for updates" first.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$activity = UpdatePackage::run(
|
||||
server: $this->server,
|
||||
packageManager: $this->packageManager,
|
||||
@@ -84,8 +88,8 @@ class Patches extends Component
|
||||
all: true
|
||||
);
|
||||
$this->dispatch('activityMonitor', $activity->id, ServerPackageUpdated::class);
|
||||
} catch (\Exception $e) {
|
||||
$this->dispatch('error', message: $e->getMessage());
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -286,18 +286,22 @@ class Show extends Component
|
||||
|
||||
public function checkLocalhostConnection()
|
||||
{
|
||||
$this->syncData(true);
|
||||
['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection();
|
||||
if ($uptime) {
|
||||
$this->dispatch('success', 'Server is reachable.');
|
||||
$this->server->settings->is_reachable = $this->isReachable = true;
|
||||
$this->server->settings->is_usable = $this->isUsable = true;
|
||||
$this->server->settings->save();
|
||||
ServerReachabilityChanged::dispatch($this->server);
|
||||
} else {
|
||||
$this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.<br><br>Check this <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a> for further help. <br><br>Error: '.$error);
|
||||
try {
|
||||
$this->syncData(true);
|
||||
['uptime' => $uptime, 'error' => $error] = $this->server->validateConnection();
|
||||
if ($uptime) {
|
||||
$this->dispatch('success', 'Server is reachable.');
|
||||
$this->server->settings->is_reachable = $this->isReachable = true;
|
||||
$this->server->settings->is_usable = $this->isUsable = true;
|
||||
$this->server->settings->save();
|
||||
ServerReachabilityChanged::dispatch($this->server);
|
||||
} else {
|
||||
$this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.<br><br>Check this <a target="_blank" class="underline" href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a> for further help. <br><br>Error: '.$error);
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,31 +72,39 @@ class ValidateAndInstall extends Component
|
||||
|
||||
public function retry()
|
||||
{
|
||||
$this->authorize('update', $this->server);
|
||||
$this->uptime = null;
|
||||
$this->supported_os_type = null;
|
||||
$this->prerequisites_installed = null;
|
||||
$this->docker_installed = null;
|
||||
$this->docker_compose_installed = null;
|
||||
$this->docker_version = null;
|
||||
$this->error = null;
|
||||
$this->number_of_tries = 0;
|
||||
$this->init();
|
||||
try {
|
||||
$this->authorize('update', $this->server);
|
||||
$this->uptime = null;
|
||||
$this->supported_os_type = null;
|
||||
$this->prerequisites_installed = null;
|
||||
$this->docker_installed = null;
|
||||
$this->docker_compose_installed = null;
|
||||
$this->docker_version = null;
|
||||
$this->error = null;
|
||||
$this->number_of_tries = 0;
|
||||
$this->init();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function validateConnection()
|
||||
{
|
||||
$this->authorize('update', $this->server);
|
||||
['uptime' => $this->uptime, 'error' => $error] = $this->server->validateConnection();
|
||||
if (! $this->uptime) {
|
||||
$this->error = 'Server is not reachable. Please validate your configuration and connection.<br>Check this <a target="_blank" class="text-black underline dark:text-white" href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a> for further help. <br><br><div class="text-error">Error: '.$error.'</div>';
|
||||
$this->server->update([
|
||||
'validation_logs' => $this->error,
|
||||
]);
|
||||
try {
|
||||
$this->authorize('update', $this->server);
|
||||
['uptime' => $this->uptime, 'error' => $error] = $this->server->validateConnection();
|
||||
if (! $this->uptime) {
|
||||
$this->error = 'Server is not reachable. Please validate your configuration and connection.<br>Check this <a target="_blank" class="text-black underline dark:text-white" href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a> for further help. <br><br><div class="text-error">Error: '.$error.'</div>';
|
||||
$this->server->update([
|
||||
'validation_logs' => $this->error,
|
||||
]);
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
$this->dispatch('validateOS');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
$this->dispatch('validateOS');
|
||||
}
|
||||
|
||||
public function validateOS()
|
||||
|
||||
@@ -57,9 +57,13 @@ class Show extends Component
|
||||
|
||||
public function switch()
|
||||
{
|
||||
$this->authorize('view', $this->project);
|
||||
$this->view = $this->view === 'normal' ? 'dev' : 'normal';
|
||||
$this->getDevView();
|
||||
try {
|
||||
$this->authorize('view', $this->project);
|
||||
$this->view = $this->view === 'normal' ? 'dev' : 'normal';
|
||||
$this->getDevView();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDevView()
|
||||
|
||||
@@ -51,9 +51,13 @@ class Index extends Component
|
||||
|
||||
public function switch()
|
||||
{
|
||||
$this->authorize('view', $this->team);
|
||||
$this->view = $this->view === 'normal' ? 'dev' : 'normal';
|
||||
$this->getDevView();
|
||||
try {
|
||||
$this->authorize('view', $this->team);
|
||||
$this->view = $this->view === 'normal' ? 'dev' : 'normal';
|
||||
$this->getDevView();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDevView()
|
||||
|
||||
@@ -18,7 +18,11 @@ class Show extends Component
|
||||
if (! $this->storage) {
|
||||
abort(404);
|
||||
}
|
||||
$this->authorize('view', $this->storage);
|
||||
try {
|
||||
$this->authorize('view', $this->storage);
|
||||
} catch (\Illuminate\Auth\Access\AuthorizationException) {
|
||||
return $this->redirectRoute('storage.index', navigate: true);
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
||||
+19
-15
@@ -95,23 +95,27 @@ class Index extends Component
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$currentTeam = currentTeam();
|
||||
$this->authorize('delete', $currentTeam);
|
||||
$currentTeam->delete();
|
||||
try {
|
||||
$currentTeam = currentTeam();
|
||||
$this->authorize('delete', $currentTeam);
|
||||
$currentTeam->delete();
|
||||
|
||||
$currentTeam->members->each(function ($user) use ($currentTeam) {
|
||||
if ($user->id === Auth::id()) {
|
||||
return;
|
||||
}
|
||||
$user->teams()->detach($currentTeam);
|
||||
$session = DB::table('sessions')->where('user_id', $user->id)->first();
|
||||
if ($session) {
|
||||
DB::table('sessions')->where('id', $session->id)->delete();
|
||||
}
|
||||
});
|
||||
$currentTeam->members->each(function ($user) use ($currentTeam) {
|
||||
if ($user->id === Auth::id()) {
|
||||
return;
|
||||
}
|
||||
$user->teams()->detach($currentTeam);
|
||||
$session = DB::table('sessions')->where('user_id', $user->id)->first();
|
||||
if ($session) {
|
||||
DB::table('sessions')->where('id', $session->id)->delete();
|
||||
}
|
||||
});
|
||||
|
||||
refreshSession();
|
||||
refreshSession();
|
||||
|
||||
return redirect()->route('team.index');
|
||||
return redirect()->route('team.index');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -59,7 +59,7 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, Sen
|
||||
$team->webhookNotificationSettings()->create();
|
||||
});
|
||||
|
||||
static::saving(function ($team) {
|
||||
static::updating(function ($team) {
|
||||
if (auth()->user()?->isMember()) {
|
||||
throw new \Exception('You are not allowed to update this team.');
|
||||
}
|
||||
|
||||
@@ -12,11 +12,6 @@ class ApiTokenPolicy
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
// Users can view their own API tokens
|
||||
return true;
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -25,12 +20,7 @@ class ApiTokenPolicy
|
||||
*/
|
||||
public function view(User $user, PersonalAccessToken $token): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
// Users can only view their own tokens
|
||||
return $user->id === $token->tokenable_id && $token->tokenable_type === User::class;
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,11 +28,6 @@ class ApiTokenPolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
// All authenticated users can create their own API tokens
|
||||
return true;
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -51,12 +36,7 @@ class ApiTokenPolicy
|
||||
*/
|
||||
public function update(User $user, PersonalAccessToken $token): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
// Users can only update their own tokens
|
||||
return $user->id === $token->tokenable_id && $token->tokenable_type === User::class;
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,12 +44,7 @@ class ApiTokenPolicy
|
||||
*/
|
||||
public function delete(User $user, PersonalAccessToken $token): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
// Users can only delete their own tokens
|
||||
return $user->id === $token->tokenable_id && $token->tokenable_type === User::class;
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,11 +52,6 @@ class ApiTokenPolicy
|
||||
*/
|
||||
public function manage(User $user): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
// All authenticated users can manage their own API tokens
|
||||
return true;
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -90,7 +60,6 @@ class ApiTokenPolicy
|
||||
*/
|
||||
public function useRootPermissions(User $user): bool
|
||||
{
|
||||
// Only admins and owners can use root permissions
|
||||
return $user->isAdmin() || $user->isOwner();
|
||||
}
|
||||
|
||||
@@ -99,11 +68,14 @@ class ApiTokenPolicy
|
||||
*/
|
||||
public function useWritePermissions(User $user): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
// Only admins and owners can use write permissions
|
||||
return $user->isAdmin() || $user->isOwner();
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can use deploy permissions for API tokens.
|
||||
*/
|
||||
public function useDeployPermissions(User $user): bool
|
||||
{
|
||||
return $user->isAdmin() || $user->isOwner();
|
||||
}
|
||||
}
|
||||
@@ -13,10 +13,6 @@ class ApplicationPolicy
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
return true;
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -25,11 +21,9 @@ class ApplicationPolicy
|
||||
*/
|
||||
public function view(User $user, Application $application): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
return true;
|
||||
*/
|
||||
return true;
|
||||
$teamId = $this->getTeamId($application);
|
||||
|
||||
return $teamId !== null && $user->teams->contains('id', $teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,15 +31,7 @@ class ApplicationPolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
*/
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,15 +39,17 @@ class ApplicationPolicy
|
||||
*/
|
||||
public function update(User $user, Application $application): Response
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
if ($user->isAdmin()) {
|
||||
$teamId = $this->getTeamId($application);
|
||||
|
||||
if ($teamId === null) {
|
||||
return Response::deny('Application team not found.');
|
||||
}
|
||||
|
||||
if ($user->isAdminOfTeam($teamId)) {
|
||||
return Response::allow();
|
||||
}
|
||||
|
||||
return Response::deny('As a member, you cannot update this application.<br/><br/>You need at least admin or owner permissions.');
|
||||
*/
|
||||
return Response::allow();
|
||||
return Response::deny('You need at least admin or owner permissions to update this application.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,15 +57,9 @@ class ApplicationPolicy
|
||||
*/
|
||||
public function delete(User $user, Application $application): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
if ($user->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
$teamId = $this->getTeamId($application);
|
||||
|
||||
return false;
|
||||
*/
|
||||
return true;
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,11 +67,7 @@ class ApplicationPolicy
|
||||
*/
|
||||
public function restore(User $user, Application $application): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
return true;
|
||||
*/
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,11 +75,7 @@ class ApplicationPolicy
|
||||
*/
|
||||
public function forceDelete(User $user, Application $application): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
return $user->isAdmin() && $user->teams->contains('id', $application->team()->first()->id);
|
||||
*/
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,11 +83,9 @@ class ApplicationPolicy
|
||||
*/
|
||||
public function deploy(User $user, Application $application): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
return $user->teams->contains('id', $application->team()->first()->id);
|
||||
*/
|
||||
return true;
|
||||
$teamId = $this->getTeamId($application);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,11 +93,9 @@ class ApplicationPolicy
|
||||
*/
|
||||
public function manageDeployments(User $user, Application $application): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
return $user->isAdmin() && $user->teams->contains('id', $application->team()->first()->id);
|
||||
*/
|
||||
return true;
|
||||
$teamId = $this->getTeamId($application);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,11 +103,9 @@ class ApplicationPolicy
|
||||
*/
|
||||
public function manageEnvironment(User $user, Application $application): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
return $user->isAdmin() && $user->teams->contains('id', $application->team()->first()->id);
|
||||
*/
|
||||
return true;
|
||||
$teamId = $this->getTeamId($application);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,10 +113,11 @@ class ApplicationPolicy
|
||||
*/
|
||||
public function cleanupDeploymentQueue(User $user): bool
|
||||
{
|
||||
// Authorization temporarily disabled
|
||||
/*
|
||||
return $user->isAdmin();
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getTeamId(Application $application): ?int
|
||||
{
|
||||
return $application->team()?->id;
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,9 @@ class ApplicationPreviewPolicy
|
||||
*/
|
||||
public function view(User $user, ApplicationPreview $applicationPreview): bool
|
||||
{
|
||||
// return $user->teams->contains('id', $applicationPreview->application->team()->first()->id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($applicationPreview);
|
||||
|
||||
return $teamId !== null && $user->teams->contains('id', $teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,21 +31,25 @@ class ApplicationPreviewPolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function update(User $user, ApplicationPreview $applicationPreview)
|
||||
public function update(User $user, ApplicationPreview $applicationPreview): Response
|
||||
{
|
||||
// if ($user->isAdmin()) {
|
||||
// return Response::allow();
|
||||
// }
|
||||
$teamId = $this->getTeamId($applicationPreview);
|
||||
|
||||
// return Response::deny('As a member, you cannot update this preview.<br/><br/>You need at least admin or owner permissions.');
|
||||
return true;
|
||||
if ($teamId === null) {
|
||||
return Response::deny('Application preview team not found.');
|
||||
}
|
||||
|
||||
if ($user->isAdminOfTeam($teamId)) {
|
||||
return Response::allow();
|
||||
}
|
||||
|
||||
return Response::deny('You need at least admin or owner permissions to update this preview.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,8 +57,9 @@ class ApplicationPreviewPolicy
|
||||
*/
|
||||
public function delete(User $user, ApplicationPreview $applicationPreview): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $applicationPreview->application->team()->first()->id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($applicationPreview);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,8 +67,7 @@ class ApplicationPreviewPolicy
|
||||
*/
|
||||
public function restore(User $user, ApplicationPreview $applicationPreview): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $applicationPreview->application->team()->first()->id);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,8 +75,7 @@ class ApplicationPreviewPolicy
|
||||
*/
|
||||
public function forceDelete(User $user, ApplicationPreview $applicationPreview): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $applicationPreview->application->team()->first()->id);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,8 +83,9 @@ class ApplicationPreviewPolicy
|
||||
*/
|
||||
public function deploy(User $user, ApplicationPreview $applicationPreview): bool
|
||||
{
|
||||
// return $user->teams->contains('id', $applicationPreview->application->team()->first()->id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($applicationPreview);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,7 +93,13 @@ class ApplicationPreviewPolicy
|
||||
*/
|
||||
public function manageDeployments(User $user, ApplicationPreview $applicationPreview): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $applicationPreview->application->team()->first()->id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($applicationPreview);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
private function getTeamId(ApplicationPreview $applicationPreview): ?int
|
||||
{
|
||||
return $applicationPreview->application?->team()?->id;
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,9 @@ class ApplicationSettingPolicy
|
||||
*/
|
||||
public function view(User $user, ApplicationSetting $applicationSetting): bool
|
||||
{
|
||||
// return $user->teams->contains('id', $applicationSetting->application->team()->first()->id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($applicationSetting);
|
||||
|
||||
return $teamId !== null && $user->teams->contains('id', $teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,8 +30,7 @@ class ApplicationSettingPolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,8 +38,9 @@ class ApplicationSettingPolicy
|
||||
*/
|
||||
public function update(User $user, ApplicationSetting $applicationSetting): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $applicationSetting->application->team()->first()->id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($applicationSetting);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,8 +48,9 @@ class ApplicationSettingPolicy
|
||||
*/
|
||||
public function delete(User $user, ApplicationSetting $applicationSetting): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $applicationSetting->application->team()->first()->id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($applicationSetting);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,8 +58,7 @@ class ApplicationSettingPolicy
|
||||
*/
|
||||
public function restore(User $user, ApplicationSetting $applicationSetting): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $applicationSetting->application->team()->first()->id);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,7 +66,11 @@ class ApplicationSettingPolicy
|
||||
*/
|
||||
public function forceDelete(User $user, ApplicationSetting $applicationSetting): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $applicationSetting->application->team()->first()->id);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getTeamId(ApplicationSetting $applicationSetting): ?int
|
||||
{
|
||||
return $applicationSetting->application?->team()?->id;
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,9 @@ class DatabasePolicy
|
||||
*/
|
||||
public function view(User $user, $database): bool
|
||||
{
|
||||
// return $user->teams->contains('id', $database->team()->first()->id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($database);
|
||||
|
||||
return $teamId !== null && $user->teams->contains('id', $teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,21 +30,25 @@ class DatabasePolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function update(User $user, $database)
|
||||
public function update(User $user, $database): Response
|
||||
{
|
||||
// if ($user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id)) {
|
||||
// return Response::allow();
|
||||
// }
|
||||
$teamId = $this->getTeamId($database);
|
||||
|
||||
// return Response::deny('As a member, you cannot update this database.<br/><br/>You need at least admin or owner permissions.');
|
||||
return true;
|
||||
if ($teamId === null) {
|
||||
return Response::deny('Database team not found.');
|
||||
}
|
||||
|
||||
if ($user->isAdminOfTeam($teamId)) {
|
||||
return Response::allow();
|
||||
}
|
||||
|
||||
return Response::deny('You need at least admin or owner permissions to update this database.');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,8 +56,9 @@ class DatabasePolicy
|
||||
*/
|
||||
public function delete(User $user, $database): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($database);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,8 +66,7 @@ class DatabasePolicy
|
||||
*/
|
||||
public function restore(User $user, $database): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,8 +74,7 @@ class DatabasePolicy
|
||||
*/
|
||||
public function forceDelete(User $user, $database): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,8 +82,9 @@ class DatabasePolicy
|
||||
*/
|
||||
public function manage(User $user, $database): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($database);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,8 +92,9 @@ class DatabasePolicy
|
||||
*/
|
||||
public function manageBackups(User $user, $database): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($database);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,7 +102,17 @@ class DatabasePolicy
|
||||
*/
|
||||
public function manageEnvironment(User $user, $database): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $database->team()->first()->id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($database);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
private function getTeamId($database): ?int
|
||||
{
|
||||
if (method_exists($database, 'team')) {
|
||||
return $database->team()?->id;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,9 @@ class EnvironmentPolicy
|
||||
*/
|
||||
public function view(User $user, Environment $environment): bool
|
||||
{
|
||||
// return $user->teams->contains('id', $environment->project->team_id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($environment);
|
||||
|
||||
return $teamId !== null && $user->teams->contains('id', $teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,8 +30,7 @@ class EnvironmentPolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,8 +38,9 @@ class EnvironmentPolicy
|
||||
*/
|
||||
public function update(User $user, Environment $environment): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $environment->project->team_id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($environment);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,8 +48,9 @@ class EnvironmentPolicy
|
||||
*/
|
||||
public function delete(User $user, Environment $environment): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $environment->project->team_id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($environment);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,8 +58,7 @@ class EnvironmentPolicy
|
||||
*/
|
||||
public function restore(User $user, Environment $environment): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $environment->project->team_id);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,7 +66,11 @@ class EnvironmentPolicy
|
||||
*/
|
||||
public function forceDelete(User $user, Environment $environment): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $environment->project->team_id);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getTeamId(Environment $environment): ?int
|
||||
{
|
||||
return $environment->project?->team_id;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,9 @@ class EnvironmentVariablePolicy
|
||||
*/
|
||||
public function view(User $user, EnvironmentVariable $environmentVariable): bool
|
||||
{
|
||||
return true;
|
||||
$teamId = $this->getTeamId($environmentVariable);
|
||||
|
||||
return $teamId !== null && $user->teams->contains('id', $teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,7 +30,7 @@ class EnvironmentVariablePolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,7 +38,9 @@ class EnvironmentVariablePolicy
|
||||
*/
|
||||
public function update(User $user, EnvironmentVariable $environmentVariable): bool
|
||||
{
|
||||
return true;
|
||||
$teamId = $this->getTeamId($environmentVariable);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,7 +48,9 @@ class EnvironmentVariablePolicy
|
||||
*/
|
||||
public function delete(User $user, EnvironmentVariable $environmentVariable): bool
|
||||
{
|
||||
return true;
|
||||
$teamId = $this->getTeamId($environmentVariable);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +58,7 @@ class EnvironmentVariablePolicy
|
||||
*/
|
||||
public function restore(User $user, EnvironmentVariable $environmentVariable): bool
|
||||
{
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,7 +66,7 @@ class EnvironmentVariablePolicy
|
||||
*/
|
||||
public function forceDelete(User $user, EnvironmentVariable $environmentVariable): bool
|
||||
{
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,6 +74,19 @@ class EnvironmentVariablePolicy
|
||||
*/
|
||||
public function manageEnvironment(User $user, EnvironmentVariable $environmentVariable): bool
|
||||
{
|
||||
return true;
|
||||
$teamId = $this->getTeamId($environmentVariable);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
private function getTeamId(EnvironmentVariable $environmentVariable): ?int
|
||||
{
|
||||
$resource = $environmentVariable->resourceable;
|
||||
|
||||
if (! $resource || ! method_exists($resource, 'team')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $resource->team()?->id;
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,11 @@ class GithubAppPolicy
|
||||
*/
|
||||
public function view(User $user, GithubApp $githubApp): bool
|
||||
{
|
||||
// return $user->teams->contains('id', $githubApp->team_id) || $githubApp->is_system_wide;
|
||||
return true;
|
||||
if ($githubApp->is_system_wide) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $user->teams->contains('id', $githubApp->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,8 +32,7 @@ class GithubAppPolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,12 +41,10 @@ class GithubAppPolicy
|
||||
public function update(User $user, GithubApp $githubApp): bool
|
||||
{
|
||||
if ($githubApp->is_system_wide) {
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->canAccessSystemResources();
|
||||
}
|
||||
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $githubApp->team_id);
|
||||
return true;
|
||||
return $user->isAdminOfTeam($githubApp->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,12 +53,10 @@ class GithubAppPolicy
|
||||
public function delete(User $user, GithubApp $githubApp): bool
|
||||
{
|
||||
if ($githubApp->is_system_wide) {
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->canAccessSystemResources();
|
||||
}
|
||||
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $githubApp->team_id);
|
||||
return true;
|
||||
return $user->isAdminOfTeam($githubApp->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,11 @@ class NotificationPolicy
|
||||
*/
|
||||
public function view(User $user, Model $notificationSettings): bool
|
||||
{
|
||||
// Check if the notification settings belong to the user's current team
|
||||
if (! $notificationSettings->team) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// return $user->teams()->where('teams.id', $notificationSettings->team->id)->exists();
|
||||
return true;
|
||||
return $user->teams->contains('id', $notificationSettings->team->id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -26,14 +24,13 @@ class NotificationPolicy
|
||||
*/
|
||||
public function update(User $user, Model $notificationSettings): bool
|
||||
{
|
||||
// Check if the notification settings belong to the user's current team
|
||||
if (! $notificationSettings->team) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only owners and admins can update notification settings
|
||||
// return $user->isAdmin() || $user->isOwner();
|
||||
return true;
|
||||
$teamId = $notificationSettings->team->id;
|
||||
|
||||
return $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,8 +38,7 @@ class NotificationPolicy
|
||||
*/
|
||||
public function manage(User $user, Model $notificationSettings): bool
|
||||
{
|
||||
// return $this->update($user, $notificationSettings);
|
||||
return true;
|
||||
return $this->update($user, $notificationSettings);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,7 +46,6 @@ class NotificationPolicy
|
||||
*/
|
||||
public function sendTest(User $user, Model $notificationSettings): bool
|
||||
{
|
||||
// return $this->update($user, $notificationSettings);
|
||||
return true;
|
||||
return $this->update($user, $notificationSettings);
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,7 @@ class ProjectPolicy
|
||||
*/
|
||||
public function view(User $user, Project $project): bool
|
||||
{
|
||||
// return $user->teams->contains('id', $project->team_id);
|
||||
return true;
|
||||
return $user->teams->contains('id', $project->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,8 +28,7 @@ class ProjectPolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,8 +36,7 @@ class ProjectPolicy
|
||||
*/
|
||||
public function update(User $user, Project $project): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $project->team_id);
|
||||
return true;
|
||||
return $user->isAdminOfTeam($project->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,8 +44,7 @@ class ProjectPolicy
|
||||
*/
|
||||
public function delete(User $user, Project $project): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $project->team_id);
|
||||
return true;
|
||||
return $user->isAdminOfTeam($project->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,8 +52,7 @@ class ProjectPolicy
|
||||
*/
|
||||
public function restore(User $user, Project $project): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $project->team_id);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,7 +60,6 @@ class ProjectPolicy
|
||||
*/
|
||||
public function forceDelete(User $user, Project $project): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $project->team_id);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -38,8 +38,7 @@ class ResourceCreatePolicy
|
||||
*/
|
||||
public function createAny(User $user): bool
|
||||
{
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,8 +50,7 @@ class ResourceCreatePolicy
|
||||
return false;
|
||||
}
|
||||
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,8 +28,7 @@ class ServerPolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,8 +36,7 @@ class ServerPolicy
|
||||
*/
|
||||
public function update(User $user, Server $server): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $server->team_id);
|
||||
return true;
|
||||
return $user->isAdminOfTeam($server->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,8 +44,7 @@ class ServerPolicy
|
||||
*/
|
||||
public function delete(User $user, Server $server): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $server->team_id);
|
||||
return true;
|
||||
return $user->isAdminOfTeam($server->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,8 +68,7 @@ class ServerPolicy
|
||||
*/
|
||||
public function manageProxy(User $user, Server $server): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $server->team_id);
|
||||
return true;
|
||||
return $user->isAdminOfTeam($server->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,8 +76,7 @@ class ServerPolicy
|
||||
*/
|
||||
public function manageSentinel(User $user, Server $server): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $server->team_id);
|
||||
return true;
|
||||
return $user->isAdminOfTeam($server->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,8 +84,7 @@ class ServerPolicy
|
||||
*/
|
||||
public function manageCaCertificate(User $user, Server $server): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $server->team_id);
|
||||
return true;
|
||||
return $user->isAdminOfTeam($server->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,7 +92,6 @@ class ServerPolicy
|
||||
*/
|
||||
public function viewSecurity(User $user, Server $server): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $server->team_id);
|
||||
return true;
|
||||
return $user->isAdminOfTeam($server->team_id);
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,7 @@ class ServiceApplicationPolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,8 +29,7 @@ class ServiceApplicationPolicy
|
||||
*/
|
||||
public function update(User $user, ServiceApplication $serviceApplication): bool
|
||||
{
|
||||
// return Gate::allows('update', $serviceApplication->service);
|
||||
return true;
|
||||
return Gate::allows('update', $serviceApplication->service);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,8 +37,7 @@ class ServiceApplicationPolicy
|
||||
*/
|
||||
public function delete(User $user, ServiceApplication $serviceApplication): bool
|
||||
{
|
||||
// return Gate::allows('delete', $serviceApplication->service);
|
||||
return true;
|
||||
return Gate::allows('delete', $serviceApplication->service);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,8 +45,7 @@ class ServiceApplicationPolicy
|
||||
*/
|
||||
public function restore(User $user, ServiceApplication $serviceApplication): bool
|
||||
{
|
||||
// return Gate::allows('update', $serviceApplication->service);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +53,6 @@ class ServiceApplicationPolicy
|
||||
*/
|
||||
public function forceDelete(User $user, ServiceApplication $serviceApplication): bool
|
||||
{
|
||||
// return Gate::allows('delete', $serviceApplication->service);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ class ServiceDatabasePolicy
|
||||
*/
|
||||
public function view(User $user, ServiceDatabase $serviceDatabase): bool
|
||||
{
|
||||
return true;
|
||||
return Gate::allows('view', $serviceDatabase->service);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -21,8 +21,7 @@ class ServiceDatabasePolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -30,9 +29,7 @@ class ServiceDatabasePolicy
|
||||
*/
|
||||
public function update(User $user, ServiceDatabase $serviceDatabase): bool
|
||||
{
|
||||
|
||||
// return Gate::allows('update', $serviceDatabase->service);
|
||||
return true;
|
||||
return Gate::allows('update', $serviceDatabase->service);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,8 +37,7 @@ class ServiceDatabasePolicy
|
||||
*/
|
||||
public function delete(User $user, ServiceDatabase $serviceDatabase): bool
|
||||
{
|
||||
// return Gate::allows('delete', $serviceDatabase->service);
|
||||
return true;
|
||||
return Gate::allows('delete', $serviceDatabase->service);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,8 +45,7 @@ class ServiceDatabasePolicy
|
||||
*/
|
||||
public function restore(User $user, ServiceDatabase $serviceDatabase): bool
|
||||
{
|
||||
// return Gate::allows('update', $serviceDatabase->service);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,12 +53,14 @@ class ServiceDatabasePolicy
|
||||
*/
|
||||
public function forceDelete(User $user, ServiceDatabase $serviceDatabase): bool
|
||||
{
|
||||
// return Gate::allows('delete', $serviceDatabase->service);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can manage database backups.
|
||||
*/
|
||||
public function manageBackups(User $user, ServiceDatabase $serviceDatabase): bool
|
||||
{
|
||||
return true;
|
||||
return Gate::allows('update', $serviceDatabase->service);
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,9 @@ class ServicePolicy
|
||||
*/
|
||||
public function view(User $user, Service $service): bool
|
||||
{
|
||||
return true;
|
||||
$teamId = $this->getTeamId($service);
|
||||
|
||||
return $teamId !== null && $user->teams->contains('id', $teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -28,8 +30,7 @@ class ServicePolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,13 +38,9 @@ class ServicePolicy
|
||||
*/
|
||||
public function update(User $user, Service $service): bool
|
||||
{
|
||||
$team = $service->team();
|
||||
if (! $team) {
|
||||
return false;
|
||||
}
|
||||
$teamId = $this->getTeamId($service);
|
||||
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $team->id);
|
||||
return true;
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,12 +48,9 @@ class ServicePolicy
|
||||
*/
|
||||
public function delete(User $user, Service $service): bool
|
||||
{
|
||||
// if ($user->isAdmin()) {
|
||||
// return true;
|
||||
// }
|
||||
$teamId = $this->getTeamId($service);
|
||||
|
||||
// return false;
|
||||
return true;
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,8 +58,7 @@ class ServicePolicy
|
||||
*/
|
||||
public function restore(User $user, Service $service): bool
|
||||
{
|
||||
// return true;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,23 +66,17 @@ class ServicePolicy
|
||||
*/
|
||||
public function forceDelete(User $user, Service $service): bool
|
||||
{
|
||||
// if ($user->isAdmin()) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// return false;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can stop the service.
|
||||
*/
|
||||
public function stop(User $user, Service $service): bool
|
||||
{
|
||||
$team = $service->team();
|
||||
if (! $team) {
|
||||
return false;
|
||||
}
|
||||
$teamId = $this->getTeamId($service);
|
||||
|
||||
// return $user->teams->contains('id', $team->id);
|
||||
return true;
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,13 +84,9 @@ class ServicePolicy
|
||||
*/
|
||||
public function manageEnvironment(User $user, Service $service): bool
|
||||
{
|
||||
$team = $service->team();
|
||||
if (! $team) {
|
||||
return false;
|
||||
}
|
||||
$teamId = $this->getTeamId($service);
|
||||
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $team->id);
|
||||
return true;
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,18 +94,23 @@ class ServicePolicy
|
||||
*/
|
||||
public function deploy(User $user, Service $service): bool
|
||||
{
|
||||
$team = $service->team();
|
||||
if (! $team) {
|
||||
return false;
|
||||
}
|
||||
$teamId = $this->getTeamId($service);
|
||||
|
||||
// return $user->teams->contains('id', $team->id);
|
||||
return true;
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can access the terminal.
|
||||
*/
|
||||
public function accessTerminal(User $user, Service $service): bool
|
||||
{
|
||||
// return $user->isAdmin() || $user->teams->contains('id', $service->team()->id);
|
||||
return true;
|
||||
$teamId = $this->getTeamId($service);
|
||||
|
||||
return $teamId !== null && $user->isAdminOfTeam($teamId);
|
||||
}
|
||||
|
||||
private function getTeamId(Service $service): ?int
|
||||
{
|
||||
return $service->team()?->id;
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,7 @@ class SharedEnvironmentVariablePolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,8 +36,7 @@ class SharedEnvironmentVariablePolicy
|
||||
*/
|
||||
public function update(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id);
|
||||
return true;
|
||||
return $user->isAdminOfTeam($sharedEnvironmentVariable->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,8 +44,7 @@ class SharedEnvironmentVariablePolicy
|
||||
*/
|
||||
public function delete(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id);
|
||||
return true;
|
||||
return $user->isAdminOfTeam($sharedEnvironmentVariable->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,8 +52,7 @@ class SharedEnvironmentVariablePolicy
|
||||
*/
|
||||
public function restore(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,8 +60,7 @@ class SharedEnvironmentVariablePolicy
|
||||
*/
|
||||
public function forceDelete(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,7 +68,6 @@ class SharedEnvironmentVariablePolicy
|
||||
*/
|
||||
public function manageEnvironment(User $user, SharedEnvironmentVariable $sharedEnvironmentVariable): bool
|
||||
{
|
||||
// return $user->isAdmin() && $user->teams->contains('id', $sharedEnvironmentVariable->team_id);
|
||||
return true;
|
||||
return $user->isAdminOfTeam($sharedEnvironmentVariable->team_id);
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,7 @@ class StandaloneDockerPolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,7 +36,7 @@ class StandaloneDockerPolicy
|
||||
*/
|
||||
public function update(User $user, StandaloneDocker $standaloneDocker): bool
|
||||
{
|
||||
return $user->teams->contains('id', $standaloneDocker->server->team_id);
|
||||
return $user->isAdminOfTeam($standaloneDocker->server->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,7 +44,7 @@ class StandaloneDockerPolicy
|
||||
*/
|
||||
public function delete(User $user, StandaloneDocker $standaloneDocker): bool
|
||||
{
|
||||
return $user->teams->contains('id', $standaloneDocker->server->team_id);
|
||||
return $user->isAdminOfTeam($standaloneDocker->server->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,8 +28,7 @@ class SwarmDockerPolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
// return $user->isAdmin();
|
||||
return true;
|
||||
return $user->isAdmin();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,7 +36,7 @@ class SwarmDockerPolicy
|
||||
*/
|
||||
public function update(User $user, SwarmDocker $swarmDocker): bool
|
||||
{
|
||||
return $user->teams->contains('id', $swarmDocker->server->team_id);
|
||||
return $user->isAdminOfTeam($swarmDocker->server->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,7 +44,7 @@ class SwarmDockerPolicy
|
||||
*/
|
||||
public function delete(User $user, SwarmDocker $swarmDocker): bool
|
||||
{
|
||||
return $user->teams->contains('id', $swarmDocker->server->team_id);
|
||||
return $user->isAdminOfTeam($swarmDocker->server->team_id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user