mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-14 14:17:18 +00:00
Merge branch 'next' into feat/api/tag-management
This commit is contained in:
62 files changed
+1577
-244
No files matched your search
+97
-12
@@ -118,7 +118,92 @@ class Application extends BaseModel
|
||||
|
||||
private static $parserVersion = '5';
|
||||
|
||||
protected $guarded = [];
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'fqdn',
|
||||
'git_repository',
|
||||
'git_branch',
|
||||
'git_commit_sha',
|
||||
'git_full_url',
|
||||
'docker_registry_image_name',
|
||||
'docker_registry_image_tag',
|
||||
'build_pack',
|
||||
'static_image',
|
||||
'install_command',
|
||||
'build_command',
|
||||
'start_command',
|
||||
'ports_exposes',
|
||||
'ports_mappings',
|
||||
'base_directory',
|
||||
'publish_directory',
|
||||
'health_check_enabled',
|
||||
'health_check_path',
|
||||
'health_check_port',
|
||||
'health_check_host',
|
||||
'health_check_method',
|
||||
'health_check_return_code',
|
||||
'health_check_scheme',
|
||||
'health_check_response_text',
|
||||
'health_check_interval',
|
||||
'health_check_timeout',
|
||||
'health_check_retries',
|
||||
'health_check_start_period',
|
||||
'health_check_type',
|
||||
'health_check_command',
|
||||
'limits_memory',
|
||||
'limits_memory_swap',
|
||||
'limits_memory_swappiness',
|
||||
'limits_memory_reservation',
|
||||
'limits_cpus',
|
||||
'limits_cpuset',
|
||||
'limits_cpu_shares',
|
||||
'status',
|
||||
'preview_url_template',
|
||||
'dockerfile',
|
||||
'dockerfile_location',
|
||||
'dockerfile_target_build',
|
||||
'custom_labels',
|
||||
'custom_docker_run_options',
|
||||
'post_deployment_command',
|
||||
'post_deployment_command_container',
|
||||
'pre_deployment_command',
|
||||
'pre_deployment_command_container',
|
||||
'manual_webhook_secret_github',
|
||||
'manual_webhook_secret_gitlab',
|
||||
'manual_webhook_secret_bitbucket',
|
||||
'manual_webhook_secret_gitea',
|
||||
'docker_compose_location',
|
||||
'docker_compose_pr_location',
|
||||
'docker_compose',
|
||||
'docker_compose_pr',
|
||||
'docker_compose_raw',
|
||||
'docker_compose_pr_raw',
|
||||
'docker_compose_domains',
|
||||
'docker_compose_custom_start_command',
|
||||
'docker_compose_custom_build_command',
|
||||
'swarm_replicas',
|
||||
'swarm_placement_constraints',
|
||||
'watch_paths',
|
||||
'redirect',
|
||||
'compose_parsing_version',
|
||||
'custom_nginx_configuration',
|
||||
'custom_network_aliases',
|
||||
'custom_healthcheck_found',
|
||||
'nixpkgsarchive',
|
||||
'is_http_basic_auth_enabled',
|
||||
'http_basic_auth_username',
|
||||
'http_basic_auth_password',
|
||||
'connect_to_docker_network',
|
||||
'force_domain_override',
|
||||
'is_container_label_escape_enabled',
|
||||
'use_build_server',
|
||||
'config_hash',
|
||||
'last_online_at',
|
||||
'restart_count',
|
||||
'last_restart_at',
|
||||
'last_restart_type',
|
||||
];
|
||||
|
||||
protected $appends = ['server_status'];
|
||||
|
||||
@@ -1145,7 +1230,7 @@ class Application extends BaseModel
|
||||
'is_accessible' => true,
|
||||
'error' => null,
|
||||
];
|
||||
} catch (\RuntimeException $ex) {
|
||||
} catch (RuntimeException $ex) {
|
||||
return [
|
||||
'is_accessible' => false,
|
||||
'error' => $ex->getMessage(),
|
||||
@@ -1202,7 +1287,7 @@ class Application extends BaseModel
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->source->getMorphClass() === \App\Models\GitlabApp::class) {
|
||||
if ($this->source->getMorphClass() === GitlabApp::class) {
|
||||
$gitlabSource = $this->source;
|
||||
$private_key = data_get($gitlabSource, 'privateKey.private_key');
|
||||
|
||||
@@ -1354,7 +1439,7 @@ class Application extends BaseModel
|
||||
$source_html_url_host = $url['host'];
|
||||
$source_html_url_scheme = $url['scheme'];
|
||||
|
||||
if ($this->source->getMorphClass() === \App\Models\GithubApp::class) {
|
||||
if ($this->source->getMorphClass() === GithubApp::class) {
|
||||
if ($this->source->is_public) {
|
||||
$fullRepoUrl = "{$this->source->html_url}/{$customRepository}";
|
||||
$escapedRepoUrl = escapeshellarg("{$this->source->html_url}/{$customRepository}");
|
||||
@@ -1409,7 +1494,7 @@ class Application extends BaseModel
|
||||
];
|
||||
}
|
||||
|
||||
if ($this->source->getMorphClass() === \App\Models\GitlabApp::class) {
|
||||
if ($this->source->getMorphClass() === GitlabApp::class) {
|
||||
$gitlabSource = $this->source;
|
||||
$private_key = data_get($gitlabSource, 'privateKey.private_key');
|
||||
|
||||
@@ -1600,7 +1685,7 @@ class Application extends BaseModel
|
||||
try {
|
||||
$yaml = Yaml::parse($this->docker_compose_raw);
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException($e->getMessage());
|
||||
throw new RuntimeException($e->getMessage());
|
||||
}
|
||||
$services = data_get($yaml, 'services');
|
||||
|
||||
@@ -1682,7 +1767,7 @@ class Application extends BaseModel
|
||||
$fileList = collect([".$workdir$composeFile"]);
|
||||
$gitRemoteStatus = $this->getGitRemoteStatus(deployment_uuid: $uuid);
|
||||
if (! $gitRemoteStatus['is_accessible']) {
|
||||
throw new \RuntimeException("Failed to read Git source:\n\n{$gitRemoteStatus['error']}");
|
||||
throw new RuntimeException('Failed to read Git source. Please verify repository access and try again.');
|
||||
}
|
||||
$getGitVersion = instant_remote_process(['git --version'], $this->destination->server, false);
|
||||
$gitVersion = str($getGitVersion)->explode(' ')->last();
|
||||
@@ -1732,15 +1817,15 @@ class Application extends BaseModel
|
||||
$this->save();
|
||||
|
||||
if (str($e->getMessage())->contains('No such file')) {
|
||||
throw new \RuntimeException("Docker Compose file not found at: $workdir$composeFile (branch: {$this->git_branch})<br><br>Check if you used the right extension (.yaml or .yml) in the compose file name.");
|
||||
throw new RuntimeException("Docker Compose file not found at: $workdir$composeFile (branch: {$this->git_branch})<br><br>Check if you used the right extension (.yaml or .yml) in the compose file name.");
|
||||
}
|
||||
if (str($e->getMessage())->contains('fatal: repository') && str($e->getMessage())->contains('does not exist')) {
|
||||
if ($this->deploymentType() === 'deploy_key') {
|
||||
throw new \RuntimeException('Your deploy key does not have access to the repository. Please check your deploy key and try again.');
|
||||
throw new RuntimeException('Your deploy key does not have access to the repository. Please check your deploy key and try again.');
|
||||
}
|
||||
throw new \RuntimeException('Repository does not exist. Please check your repository URL and try again.');
|
||||
throw new RuntimeException('Repository does not exist. Please check your repository URL and try again.');
|
||||
}
|
||||
throw new \RuntimeException($e->getMessage());
|
||||
throw new RuntimeException('Failed to read the Docker Compose file from the repository.');
|
||||
} finally {
|
||||
// Cleanup only - restoration happens in catch block
|
||||
$commands = collect([
|
||||
@@ -1793,7 +1878,7 @@ class Application extends BaseModel
|
||||
$this->base_directory = $initialBaseDirectory;
|
||||
$this->save();
|
||||
|
||||
throw new \RuntimeException("Docker Compose file not found at: $workdir$composeFile (branch: {$this->git_branch})<br><br>Check if you used the right extension (.yaml or .yml) in the compose file name.");
|
||||
throw new RuntimeException("Docker Compose file not found at: $workdir$composeFile (branch: {$this->git_branch})<br><br>Check if you used the right extension (.yaml or .yml) in the compose file name.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -265,8 +265,6 @@ class Server extends BaseModel
|
||||
'server_metadata',
|
||||
];
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
use HasSafeStringAttribute;
|
||||
|
||||
public function setValidationLogsAttribute($value): void
|
||||
|
||||
@@ -56,6 +56,7 @@ class ServerSetting extends Model
|
||||
protected $guarded = [];
|
||||
|
||||
protected $casts = [
|
||||
'force_disabled' => 'boolean',
|
||||
'force_docker_cleanup' => 'boolean',
|
||||
'docker_cleanup_threshold' => 'integer',
|
||||
'sentinel_token' => 'encrypted',
|
||||
|
||||
+12
-2
@@ -15,6 +15,7 @@ use Illuminate\Support\Facades\Storage;
|
||||
use OpenApi\Attributes as OA;
|
||||
use Spatie\Activitylog\Models\Activity;
|
||||
use Spatie\Url\Url;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
#[OA\Schema(
|
||||
@@ -47,7 +48,16 @@ class Service extends BaseModel
|
||||
|
||||
private static $parserVersion = '5';
|
||||
|
||||
protected $guarded = [];
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'docker_compose_raw',
|
||||
'docker_compose',
|
||||
'connect_to_docker_network',
|
||||
'service_type',
|
||||
'config_hash',
|
||||
'compose_parsing_version',
|
||||
];
|
||||
|
||||
protected $appends = ['server_status', 'status'];
|
||||
|
||||
@@ -1552,7 +1562,7 @@ class Service extends BaseModel
|
||||
// Generate SERVICE_NAME_* environment variables from docker-compose services
|
||||
if ($this->docker_compose) {
|
||||
try {
|
||||
$dockerCompose = \Symfony\Component\Yaml\Yaml::parse($this->docker_compose);
|
||||
$dockerCompose = Yaml::parse($this->docker_compose);
|
||||
$services = data_get($dockerCompose, 'services', []);
|
||||
foreach ($services as $serviceName => $_) {
|
||||
$envs->push('SERVICE_NAME_'.str($serviceName)->replace('-', '_')->replace('.', '_')->upper().'='.$serviceName);
|
||||
|
||||
@@ -13,12 +13,36 @@ class StandaloneClickhouse extends BaseModel
|
||||
{
|
||||
use ClearsGlobalSearchCache, HasFactory, HasMetrics, HasSafeStringAttribute, SoftDeletes;
|
||||
|
||||
protected $guarded = [];
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'clickhouse_admin_user',
|
||||
'clickhouse_admin_password',
|
||||
'is_log_drain_enabled',
|
||||
'is_include_timestamps',
|
||||
'status',
|
||||
'image',
|
||||
'is_public',
|
||||
'public_port',
|
||||
'ports_mappings',
|
||||
'limits_memory',
|
||||
'limits_memory_swap',
|
||||
'limits_memory_swappiness',
|
||||
'limits_memory_reservation',
|
||||
'limits_cpus',
|
||||
'limits_cpuset',
|
||||
'limits_cpu_shares',
|
||||
'started_at',
|
||||
'restart_count',
|
||||
'last_restart_at',
|
||||
'last_restart_type',
|
||||
'last_online_at',
|
||||
];
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
protected $casts = [
|
||||
'clickhouse_password' => 'encrypted',
|
||||
'clickhouse_admin_password' => 'encrypted',
|
||||
'public_port_timeout' => 'integer',
|
||||
'restart_count' => 'integer',
|
||||
'last_restart_at' => 'datetime',
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Jobs\ConnectProxyToNetworksJob;
|
||||
use App\Support\ValidationPatterns;
|
||||
use App\Traits\HasSafeStringAttribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
@@ -18,13 +19,23 @@ class StandaloneDocker extends BaseModel
|
||||
parent::boot();
|
||||
static::created(function ($newStandaloneDocker) {
|
||||
$server = $newStandaloneDocker->server;
|
||||
$safeNetwork = escapeshellarg($newStandaloneDocker->network);
|
||||
instant_remote_process([
|
||||
"docker network inspect $newStandaloneDocker->network >/dev/null 2>&1 || docker network create --driver overlay --attachable $newStandaloneDocker->network >/dev/null",
|
||||
"docker network inspect {$safeNetwork} >/dev/null 2>&1 || docker network create --driver overlay --attachable {$safeNetwork} >/dev/null",
|
||||
], $server, false);
|
||||
ConnectProxyToNetworksJob::dispatchSync($server);
|
||||
});
|
||||
}
|
||||
|
||||
public function setNetworkAttribute(string $value): void
|
||||
{
|
||||
if (! ValidationPatterns::isValidDockerNetwork($value)) {
|
||||
throw new \InvalidArgumentException('Invalid Docker network name. Must start with alphanumeric and contain only alphanumeric characters, dots, hyphens, and underscores.');
|
||||
}
|
||||
|
||||
$this->attributes['network'] = $value;
|
||||
}
|
||||
|
||||
public function applications()
|
||||
{
|
||||
return $this->morphMany(Application::class, 'destination');
|
||||
|
||||
@@ -13,7 +13,30 @@ class StandaloneDragonfly extends BaseModel
|
||||
{
|
||||
use ClearsGlobalSearchCache, HasFactory, HasMetrics, HasSafeStringAttribute, SoftDeletes;
|
||||
|
||||
protected $guarded = [];
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'dragonfly_password',
|
||||
'is_log_drain_enabled',
|
||||
'is_include_timestamps',
|
||||
'status',
|
||||
'image',
|
||||
'is_public',
|
||||
'public_port',
|
||||
'ports_mappings',
|
||||
'limits_memory',
|
||||
'limits_memory_swap',
|
||||
'limits_memory_swappiness',
|
||||
'limits_memory_reservation',
|
||||
'limits_cpus',
|
||||
'limits_cpuset',
|
||||
'limits_cpu_shares',
|
||||
'started_at',
|
||||
'restart_count',
|
||||
'last_restart_at',
|
||||
'last_restart_type',
|
||||
'last_online_at',
|
||||
];
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
|
||||
@@ -13,7 +13,31 @@ class StandaloneKeydb extends BaseModel
|
||||
{
|
||||
use ClearsGlobalSearchCache, HasFactory, HasMetrics, HasSafeStringAttribute, SoftDeletes;
|
||||
|
||||
protected $guarded = [];
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'keydb_password',
|
||||
'keydb_conf',
|
||||
'is_log_drain_enabled',
|
||||
'is_include_timestamps',
|
||||
'status',
|
||||
'image',
|
||||
'is_public',
|
||||
'public_port',
|
||||
'ports_mappings',
|
||||
'limits_memory',
|
||||
'limits_memory_swap',
|
||||
'limits_memory_swappiness',
|
||||
'limits_memory_reservation',
|
||||
'limits_cpus',
|
||||
'limits_cpuset',
|
||||
'limits_cpu_shares',
|
||||
'started_at',
|
||||
'restart_count',
|
||||
'last_restart_at',
|
||||
'last_restart_type',
|
||||
'last_online_at',
|
||||
];
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'server_status'];
|
||||
|
||||
|
||||
@@ -14,7 +14,32 @@ class StandaloneMariadb extends BaseModel
|
||||
{
|
||||
use ClearsGlobalSearchCache, HasFactory, HasMetrics, HasSafeStringAttribute, SoftDeletes;
|
||||
|
||||
protected $guarded = [];
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'mariadb_root_password',
|
||||
'mariadb_user',
|
||||
'mariadb_password',
|
||||
'mariadb_database',
|
||||
'mariadb_conf',
|
||||
'status',
|
||||
'image',
|
||||
'is_public',
|
||||
'public_port',
|
||||
'ports_mappings',
|
||||
'limits_memory',
|
||||
'limits_memory_swap',
|
||||
'limits_memory_swappiness',
|
||||
'limits_memory_reservation',
|
||||
'limits_cpus',
|
||||
'limits_cpuset',
|
||||
'limits_cpu_shares',
|
||||
'started_at',
|
||||
'restart_count',
|
||||
'last_restart_at',
|
||||
'last_restart_type',
|
||||
'last_online_at',
|
||||
];
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
|
||||
@@ -13,7 +13,31 @@ class StandaloneMongodb extends BaseModel
|
||||
{
|
||||
use ClearsGlobalSearchCache, HasFactory, HasMetrics, HasSafeStringAttribute, SoftDeletes;
|
||||
|
||||
protected $guarded = [];
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'mongo_conf',
|
||||
'mongo_initdb_root_username',
|
||||
'mongo_initdb_root_password',
|
||||
'mongo_initdb_database',
|
||||
'status',
|
||||
'image',
|
||||
'is_public',
|
||||
'public_port',
|
||||
'ports_mappings',
|
||||
'limits_memory',
|
||||
'limits_memory_swap',
|
||||
'limits_memory_swappiness',
|
||||
'limits_memory_reservation',
|
||||
'limits_cpus',
|
||||
'limits_cpuset',
|
||||
'limits_cpu_shares',
|
||||
'started_at',
|
||||
'restart_count',
|
||||
'last_restart_at',
|
||||
'last_restart_type',
|
||||
'last_online_at',
|
||||
];
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
|
||||
@@ -13,7 +13,32 @@ class StandaloneMysql extends BaseModel
|
||||
{
|
||||
use ClearsGlobalSearchCache, HasFactory, HasMetrics, HasSafeStringAttribute, SoftDeletes;
|
||||
|
||||
protected $guarded = [];
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'mysql_root_password',
|
||||
'mysql_user',
|
||||
'mysql_password',
|
||||
'mysql_database',
|
||||
'mysql_conf',
|
||||
'status',
|
||||
'image',
|
||||
'is_public',
|
||||
'public_port',
|
||||
'ports_mappings',
|
||||
'limits_memory',
|
||||
'limits_memory_swap',
|
||||
'limits_memory_swappiness',
|
||||
'limits_memory_reservation',
|
||||
'limits_cpus',
|
||||
'limits_cpuset',
|
||||
'limits_cpu_shares',
|
||||
'started_at',
|
||||
'restart_count',
|
||||
'last_restart_at',
|
||||
'last_restart_type',
|
||||
'last_online_at',
|
||||
];
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
|
||||
@@ -13,7 +13,34 @@ class StandalonePostgresql extends BaseModel
|
||||
{
|
||||
use ClearsGlobalSearchCache, HasFactory, HasMetrics, HasSafeStringAttribute, SoftDeletes;
|
||||
|
||||
protected $guarded = [];
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'postgres_user',
|
||||
'postgres_password',
|
||||
'postgres_db',
|
||||
'postgres_initdb_args',
|
||||
'postgres_host_auth_method',
|
||||
'postgres_conf',
|
||||
'init_scripts',
|
||||
'status',
|
||||
'image',
|
||||
'is_public',
|
||||
'public_port',
|
||||
'ports_mappings',
|
||||
'limits_memory',
|
||||
'limits_memory_swap',
|
||||
'limits_memory_swappiness',
|
||||
'limits_memory_reservation',
|
||||
'limits_cpus',
|
||||
'limits_cpuset',
|
||||
'limits_cpu_shares',
|
||||
'started_at',
|
||||
'restart_count',
|
||||
'last_restart_at',
|
||||
'last_restart_type',
|
||||
'last_online_at',
|
||||
];
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
|
||||
@@ -13,7 +13,28 @@ class StandaloneRedis extends BaseModel
|
||||
{
|
||||
use ClearsGlobalSearchCache, HasFactory, HasMetrics, HasSafeStringAttribute, SoftDeletes;
|
||||
|
||||
protected $guarded = [];
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'redis_conf',
|
||||
'status',
|
||||
'image',
|
||||
'is_public',
|
||||
'public_port',
|
||||
'ports_mappings',
|
||||
'limits_memory',
|
||||
'limits_memory_swap',
|
||||
'limits_memory_swappiness',
|
||||
'limits_memory_reservation',
|
||||
'limits_cpus',
|
||||
'limits_cpuset',
|
||||
'limits_cpu_shares',
|
||||
'started_at',
|
||||
'restart_count',
|
||||
'last_restart_at',
|
||||
'last_restart_type',
|
||||
'last_online_at',
|
||||
];
|
||||
|
||||
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
|
||||
|
||||
|
||||
@@ -2,10 +2,21 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Support\ValidationPatterns;
|
||||
|
||||
class SwarmDocker extends BaseModel
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
public function setNetworkAttribute(string $value): void
|
||||
{
|
||||
if (! ValidationPatterns::isValidDockerNetwork($value)) {
|
||||
throw new \InvalidArgumentException('Invalid Docker network name. Must start with alphanumeric and contain only alphanumeric characters, dots, hyphens, and underscores.');
|
||||
}
|
||||
|
||||
$this->attributes['network'] = $value;
|
||||
}
|
||||
|
||||
public function applications()
|
||||
{
|
||||
return $this->morphMany(Application::class, 'destination');
|
||||
|
||||
+7
-1
@@ -40,7 +40,13 @@ class Team extends Model implements SendsDiscord, SendsEmail, SendsPushover, Sen
|
||||
{
|
||||
use HasFactory, HasNotificationSettings, HasSafeStringAttribute, Notifiable;
|
||||
|
||||
protected $guarded = [];
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'description',
|
||||
'personal_team',
|
||||
'show_boarding',
|
||||
'custom_server_limit',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'personal_team' => 'boolean',
|
||||
|
||||
+16
-8
@@ -4,7 +4,9 @@ namespace App\Models;
|
||||
|
||||
use App\Jobs\UpdateStripeCustomerEmailJob;
|
||||
use App\Notifications\Channels\SendsEmail;
|
||||
use App\Notifications\TransactionalEmails\EmailChangeVerification;
|
||||
use App\Notifications\TransactionalEmails\ResetPassword as TransactionalEmailsResetPassword;
|
||||
use App\Services\ChangelogService;
|
||||
use App\Traits\DeletesUserSessions;
|
||||
use DateTimeInterface;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
@@ -41,7 +43,13 @@ class User extends Authenticatable implements SendsEmail
|
||||
{
|
||||
use DeletesUserSessions, HasApiTokens, HasFactory, Notifiable, TwoFactorAuthenticatable;
|
||||
|
||||
protected $guarded = [];
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'email',
|
||||
'password',
|
||||
'force_password_reset',
|
||||
'marketing_emails',
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
'password',
|
||||
@@ -87,7 +95,7 @@ class User extends Authenticatable implements SendsEmail
|
||||
$team['id'] = 0;
|
||||
$team['name'] = 'Root Team';
|
||||
}
|
||||
$new_team = Team::create($team);
|
||||
$new_team = Team::forceCreate($team);
|
||||
$user->teams()->attach($new_team, ['role' => 'owner']);
|
||||
});
|
||||
|
||||
@@ -190,7 +198,7 @@ class User extends Authenticatable implements SendsEmail
|
||||
$team['id'] = 0;
|
||||
$team['name'] = 'Root Team';
|
||||
}
|
||||
$new_team = Team::create($team);
|
||||
$new_team = Team::forceCreate($team);
|
||||
$this->teams()->attach($new_team, ['role' => 'owner']);
|
||||
|
||||
return $new_team;
|
||||
@@ -228,7 +236,7 @@ class User extends Authenticatable implements SendsEmail
|
||||
|
||||
public function getUnreadChangelogCount(): int
|
||||
{
|
||||
return app(\App\Services\ChangelogService::class)->getUnreadCountForUser($this);
|
||||
return app(ChangelogService::class)->getUnreadCountForUser($this);
|
||||
}
|
||||
|
||||
public function getRecipients(): array
|
||||
@@ -239,7 +247,7 @@ class User extends Authenticatable implements SendsEmail
|
||||
public function sendVerificationEmail()
|
||||
{
|
||||
$mail = new MailMessage;
|
||||
$url = Url::temporarySignedRoute(
|
||||
$url = URL::temporarySignedRoute(
|
||||
'verify.verify',
|
||||
Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
|
||||
[
|
||||
@@ -401,14 +409,14 @@ class User extends Authenticatable implements SendsEmail
|
||||
$expiryMinutes = config('constants.email_change.verification_code_expiry_minutes', 10);
|
||||
$expiresAt = Carbon::now()->addMinutes($expiryMinutes);
|
||||
|
||||
$this->update([
|
||||
$this->forceFill([
|
||||
'pending_email' => $newEmail,
|
||||
'email_change_code' => $code,
|
||||
'email_change_code_expires_at' => $expiresAt,
|
||||
]);
|
||||
])->save();
|
||||
|
||||
// Send verification email to new address
|
||||
$this->notify(new \App\Notifications\TransactionalEmails\EmailChangeVerification($this, $code, $newEmail, $expiresAt));
|
||||
$this->notify(new EmailChangeVerification($this, $code, $newEmail, $expiresAt));
|
||||
}
|
||||
|
||||
public function isEmailChangeCodeValid(string $code): bool
|
||||
|
||||
Reference in new issue
Block a user