PhyrePanel-mirror/web/app/Models/Domain.php

438 lines
20 KiB
PHP
Raw Normal View History

2024-04-22 11:14:05 +00:00
<?php
namespace App\Models;
use App\Actions\ApacheWebsiteDelete;
use App\Events\DomainIsCreated;
use App\Events\ModelDomainDeleting;
use App\ShellApi;
2024-04-26 16:42:35 +00:00
use Illuminate\Database\Eloquent\Builder;
2024-04-22 11:14:05 +00:00
use Illuminate\Database\Eloquent\Model;
2024-04-26 22:24:41 +00:00
use Modules\Docker\App\Models\DockerContainer;
2024-04-22 11:14:05 +00:00
class Domain extends Model
{
public const STATUS_ACTIVE = 'active';
public const STATUS_SUSPENDED = 'suspended';
public const STATUS_DELETED = 'deleted';
public const STATUS_DEACTIVATED = 'deactivated';
protected $fillable = [
'domain',
'domain_root',
'ip',
'hosting_subscription_id',
'server_application_type',
'server_application_settings',
'status'
];
protected $casts = [
'server_application_settings' => 'array',
];
2024-04-26 16:42:35 +00:00
protected static function booted(): void
{
static::addGlobalScope('customer', function (Builder $query) {
if (auth()->check() && auth()->guard()->name == 'web_customer') {
$query->whereHas('hostingSubscription', function ($query) {
$query->where('customer_id', auth()->user()->id);
});
}
});
}
2024-04-22 11:14:05 +00:00
public static function boot()
{
parent::boot();
static::created(function ($model) {
$findHostingSubscription = HostingSubscription::where('id', $model->hosting_subscription_id)->first();
if (! $findHostingSubscription) {
return;
}
$findHostingPlan = HostingPlan::where('id', $findHostingSubscription->hosting_plan_id)->first();
if (! $findHostingPlan) {
return;
}
$model->server_application_type = $findHostingPlan->default_server_application_type;
$model->server_application_settings = $findHostingPlan->default_server_application_settings;
if ($model->is_main == 1) {
// $allDomainsRoot = '/home/'.$this->user.'/public_html';
$model->domain_root = '/home/'.$findHostingSubscription->system_username;
$model->domain_public = '/home/'.$findHostingSubscription->system_username.'/public_html';
$model->home_root = '/home/'.$findHostingSubscription->system_username;
} else {
// $allDomainsRoot = '/home/'.$model->user.'/domains';
$model->domain_root = '/home/'.$findHostingSubscription->system_username.'/domains/'.$model->domain;
$model->domain_public = $model->domain_root.'/public_html';
$model->home_root = '/home/'.$findHostingSubscription->user;
}
$model->save();
$model->configureVirtualHost();
event(new DomainIsCreated($model));
});
static::updating(function ($model) {
$model->configureVirtualHost();
});
static::saved(function ($model) {
$model->configureVirtualHost();
});
static::deleting(function ($model) {
2024-04-30 15:03:36 +00:00
if (empty($model->domain_public)) {
return;
}
2024-04-30 23:14:27 +00:00
$findHostingSubscription = HostingSubscription::where('id', $model->hosting_subscription_id)->first();
if (! $findHostingSubscription) {
return;
}
ShellApi::safeDelete($model->domain_root, ['/home/' . $findHostingSubscription->system_username]);
2024-04-30 15:03:36 +00:00
2024-04-30 23:14:27 +00:00
$whiteListedPathsForDelete = [
'/etc/apache2/sites-available',
'/etc/apache2/sites-enabled',
];
2024-04-22 11:14:05 +00:00
2024-04-30 15:07:07 +00:00
$apacheConf = '/etc/apache2/sites-available/'.$model->domain.'.conf';
2024-04-30 23:14:27 +00:00
ShellApi::safeDelete($apacheConf, $whiteListedPathsForDelete);
2024-04-30 15:07:07 +00:00
$apacheConfEnabled = '/etc/apache2/sites-enabled/'.$model->domain.'.conf';
2024-04-30 23:14:27 +00:00
ShellApi::safeDelete($apacheConfEnabled, $whiteListedPathsForDelete);
2024-04-30 15:07:07 +00:00
// SSL
$apacheSSLConf = '/etc/apache2/sites-available/'.$model->domain.'-ssl.conf';
2024-04-30 23:14:27 +00:00
ShellApi::safeDelete($apacheSSLConf, $whiteListedPathsForDelete);
2024-04-30 15:07:07 +00:00
$apacheSSLConfEnabled = '/etc/apache2/sites-enabled/'.$model->domain.'-ssl.conf';
2024-04-30 23:14:27 +00:00
ShellApi::safeDelete($apacheSSLConfEnabled, $whiteListedPathsForDelete);
2024-04-30 15:07:07 +00:00
2024-04-22 11:14:05 +00:00
});
}
public function hostingSubscription()
{
return $this->belongsTo(HostingSubscription::class);
}
2024-04-29 08:45:47 +00:00
public function configureVirtualHost($reloadApache = true)
2024-04-22 11:14:05 +00:00
{
$findHostingSubscription = \App\Models\HostingSubscription::where('id', $this->hosting_subscription_id)
->first();
if (!$findHostingSubscription) {
throw new \Exception('Hosting subscription not found');
}
$findHostingPlan = \App\Models\HostingPlan::where('id', $findHostingSubscription->hosting_plan_id)
->first();
if (!$findHostingPlan) {
throw new \Exception('Hosting plan not found');
}
2024-04-30 14:27:45 +00:00
if (empty($this->domain_root)) {
2024-04-30 20:27:10 +00:00
throw new \Exception('Domain root not found');
2024-04-30 14:27:45 +00:00
}
2024-04-22 11:14:05 +00:00
if (!is_dir($this->domain_root)) {
2024-04-22 13:56:29 +00:00
mkdir($this->domain_root, 0711, true);
2024-04-22 11:14:05 +00:00
}
if (!is_dir($this->domain_public)) {
mkdir($this->domain_public, 0755, true);
}
if (!is_dir($this->home_root)) {
2024-04-22 13:56:29 +00:00
mkdir($this->home_root, 0711, true);
2024-04-22 11:14:05 +00:00
}
if ($this->is_installed_default_app_template == null) {
$this->is_installed_default_app_template = 1;
$this->save();
if ($this->server_application_type == 'apache_php') {
if (!is_file($this->domain_public . '/index.php')) {
$indexContent = view('actions.samples.apache.php.app-php-sample')->render();
file_put_contents($this->domain_public . '/index.php', $indexContent);
}
if (!is_dir($this->domain_public . '/templates')) {
mkdir($this->domain_public . '/templates', 0755, true);
}
if (!is_file($this->domain_public . '/templates/index.html')) {
$indexContent = view('actions.samples.apache.php.app-index-html')->render();
file_put_contents($this->domain_public . '/templates/index.html', $indexContent);
}
}
if ($this->server_application_type == 'apache_nodejs') {
if (!is_file($this->domain_public . '/app.js')) {
$indexContent = view('actions.samples.apache.nodejs.app-nodejs-sample')->render();
file_put_contents($this->domain_public . '/app.js', $indexContent);
}
if (!is_dir($this->domain_public . '/templates')) {
mkdir($this->domain_public . '/templates', 0755, true);
}
if (!is_file($this->domain_public . '/templates/index.html')) {
$indexContent = view('actions.samples.apache.nodejs.app-index-html')->render();
file_put_contents($this->domain_public . '/templates/index.html', $indexContent);
}
}
if ($this->server_application_type == 'apache_python') {
if (!is_file($this->domain_public . '/app.py')) {
$indexContent = view('actions.samples.apache.python.app-python-sample')->render();
file_put_contents($this->domain_public . '/app.py', $indexContent);
}
if (!is_file($this->domain_public . '/passenger_wsgi.py')) {
$indexContent = view('actions.samples.apache.python.app-passanger-wsgi-sample')->render();
file_put_contents($this->domain_public . '/passenger_wsgi.py', $indexContent);
}
if (!is_dir($this->domain_public . '/templates')) {
mkdir($this->domain_public . '/templates', 0755, true);
}
if (!is_file($this->domain_public . '/templates/index.html')) {
$indexContent = view('actions.samples.apache.python.app-index-html')->render();
file_put_contents($this->domain_public . '/templates/index.html', $indexContent);
}
}
}
$webUserGroup = $findHostingSubscription->system_username;
// Fix file permissions
shell_exec('chown -R '.$findHostingSubscription->system_username.':'.$webUserGroup.' '.$this->home_root);
shell_exec('chown -R '.$findHostingSubscription->system_username.':'.$webUserGroup.' '.$this->domain_root);
shell_exec('chown -R '.$findHostingSubscription->system_username.':'.$webUserGroup.' '.$this->domain_public);
2024-04-22 13:56:29 +00:00
shell_exec('chmod -R 0711 '.$this->home_root);
shell_exec('chmod -R 0711 '.$this->domain_root);
2024-04-22 11:14:05 +00:00
shell_exec('chmod -R 775 '.$this->domain_public);
2024-04-30 13:24:16 +00:00
if (!is_dir($this->domain_root.'/logs/apache2')) {
shell_exec('mkdir -p '.$this->domain_root.'/logs/apache2');
2024-04-30 10:12:14 +00:00
}
2024-04-30 13:57:08 +00:00
shell_exec('chown -R '.$findHostingSubscription->system_username.':'.$webUserGroup.' '.$this->domain_root.'/logs/apache2');
shell_exec('chmod -R 775 '.$this->domain_root.'/logs/apache2');
2024-04-30 12:55:18 +00:00
2024-05-02 08:41:06 +00:00
if (!is_file($this->domain_root.'/logs/apache2/bytes.log')) {
shell_exec('touch '.$this->domain_root.'/logs/apache2/bytes.log');
}
if (!is_file($this->domain_root.'/logs/apache2/access.log')) {
shell_exec('touch '.$this->domain_root.'/logs/apache2/access.log');
}
if (!is_file($this->domain_root.'/logs/apache2/error.log')) {
shell_exec('touch '.$this->domain_root.'/logs/apache2/error.log');
}
shell_exec('chmod -R 775 '.$this->domain_root.'/logs/apache2/bytes.log');
shell_exec('chmod -R 775 '.$this->domain_root.'/logs/apache2/access.log');
shell_exec('chmod -R 775 '.$this->domain_root.'/logs/apache2/error.log');
2024-04-22 11:14:05 +00:00
$appType = 'php';
$appVersion = '8.3';
if ($this->server_application_type == 'apache_php') {
if (isset($this->server_application_settings['php_version'])) {
$appVersion = $this->server_application_settings['php_version'];
}
if (!is_dir($this->domain_public . '/cgi-bin')) {
mkdir($this->domain_public . '/cgi-bin', 0755, true);
}
file_put_contents($this->domain_public . '/cgi-bin/php', '#!/usr/bin/php-cgi' . $appVersion . ' -cphp' . $appVersion . '-cgi.ini');
shell_exec('chown '.$findHostingSubscription->system_username.':'.$webUserGroup.' '.$this->domain_public . '/cgi-bin/php');
shell_exec('chmod -f 751 '.$this->domain_public . '/cgi-bin/php');
}
$apacheVirtualHostBuilder = new \App\VirtualHosts\ApacheVirtualHostBuilder();
$apacheVirtualHostBuilder->setDomain($this->domain);
$apacheVirtualHostBuilder->setDomainPublic($this->domain_public);
$apacheVirtualHostBuilder->setDomainRoot($this->domain_root);
$apacheVirtualHostBuilder->setHomeRoot($this->home_root);
$apacheVirtualHostBuilder->setUser($findHostingSubscription->system_username);
$apacheVirtualHostBuilder->setUserGroup($webUserGroup);
if ($this->status == self::STATUS_SUSPENDED) {
$suspendedPath = '/var/www/html/suspended';
if (!is_dir($suspendedPath)) {
mkdir($suspendedPath, 0755, true);
}
if (!is_file($suspendedPath . '/index.html')) {
$suspendedPageHtmlPath = base_path('resources/views/actions/samples/apache/html/app-suspended-page.html');
file_put_contents($suspendedPath . '/index.html', file_get_contents($suspendedPageHtmlPath));
}
$apacheVirtualHostBuilder->setDomainRoot($suspendedPath);
$apacheVirtualHostBuilder->setDomainPublic($suspendedPath);
2024-05-12 19:33:24 +00:00
} else if ($this->status == self::STATUS_DEACTIVATED) {
2024-04-22 11:14:05 +00:00
$deactivatedPath = '/var/www/html/deactivated';
if (!is_dir($deactivatedPath)) {
mkdir($deactivatedPath, 0755, true);
}
if (!is_file($deactivatedPath . '/index.html')) {
$deactivatedPageHtmlPath = base_path('resources/views/actions/samples/apache/html/app-deactivated-page.html');
file_put_contents($deactivatedPath . '/index.html', file_get_contents($deactivatedPageHtmlPath));
}
$apacheVirtualHostBuilder->setDomainRoot($deactivatedPath);
$apacheVirtualHostBuilder->setDomainPublic($deactivatedPath);
2024-05-12 19:33:24 +00:00
} else {
2024-04-22 11:14:05 +00:00
2024-05-12 19:33:24 +00:00
$apacheVirtualHostBuilder->setEnableLogs(true);
$apacheVirtualHostBuilder->setAdditionalServices($findHostingPlan->additional_services);
$apacheVirtualHostBuilder->setAppType($appType);
$apacheVirtualHostBuilder->setAppVersion($appVersion);
2024-04-22 11:14:05 +00:00
2024-05-12 19:33:24 +00:00
if ($this->server_application_type == 'apache_nodejs') {
$apacheVirtualHostBuilder->setAppType('nodejs');
$apacheVirtualHostBuilder->setPassengerAppRoot($this->domain_public);
$apacheVirtualHostBuilder->setPassengerAppType('node');
$apacheVirtualHostBuilder->setPassengerStartupFile('app.js');
if (isset($this->server_application_settings['nodejs_version'])) {
$apacheVirtualHostBuilder->setAppVersion($this->server_application_settings['nodejs_version']);
}
2024-04-22 11:14:05 +00:00
}
2024-05-12 19:33:24 +00:00
if ($this->server_application_type == 'apache_python') {
$apacheVirtualHostBuilder->setAppType('python');
$apacheVirtualHostBuilder->setPassengerAppRoot($this->domain_public);
$apacheVirtualHostBuilder->setPassengerAppType('python');
2024-04-22 11:14:05 +00:00
2024-05-12 19:33:24 +00:00
if (isset($this->server_application_settings['python_version'])) {
$apacheVirtualHostBuilder->setAppVersion($this->server_application_settings['python_version']);
}
2024-04-22 11:14:05 +00:00
}
2024-05-12 19:33:24 +00:00
if ($this->server_application_type == 'apache_ruby') {
$apacheVirtualHostBuilder->setAppType('ruby');
$apacheVirtualHostBuilder->setPassengerAppRoot($this->domain_public);
$apacheVirtualHostBuilder->setPassengerAppType('ruby');
2024-04-22 11:14:05 +00:00
2024-05-12 19:33:24 +00:00
if (isset($this->server_application_settings['ruby_version'])) {
$apacheVirtualHostBuilder->setAppVersion($this->server_application_settings['ruby_version']);
}
2024-04-22 11:14:05 +00:00
2024-05-12 19:33:24 +00:00
}
if ($this->server_application_type == 'apache_docker') {
if (isset($this->server_application_settings['docker_container_id'])) {
$findDockerContainer = DockerContainer::where('id', $this->server_application_settings['docker_container_id'])
->first();
if ($findDockerContainer) {
$apacheVirtualHostBuilder->setProxyPass('http://127.0.0.1:' . $findDockerContainer->external_port . '/');
$apacheVirtualHostBuilder->setAppType('docker');
$apacheVirtualHostBuilder->setAppVersion($appVersion);
}
2024-04-26 22:24:41 +00:00
}
}
}
2024-04-22 11:14:05 +00:00
$apacheBaseConfig = $apacheVirtualHostBuilder->buildConfig();
2024-04-26 22:24:41 +00:00
2024-04-22 11:14:05 +00:00
if (!empty($apacheBaseConfig)) {
file_put_contents('/etc/apache2/sites-available/'.$this->domain.'.conf', $apacheBaseConfig);
// check symlink exists
$symlinkExists = file_exists('/etc/apache2/sites-enabled/'.$this->domain.'.conf');
if (!$symlinkExists) {
shell_exec('ln -s /etc/apache2/sites-available/' . $this->domain . '.conf /etc/apache2/sites-enabled/' . $this->domain . '.conf');
}
}
$catchMainDomain = '';
$domainExp = explode('.', $this->domain);
if (count($domainExp) > 0) {
unset($domainExp[0]);
$catchMainDomain = implode('.', $domainExp);
}
$findDomainSSLCertificate = null;
$findMainDomainSSLCertificate = \App\Models\DomainSslCertificate::where('domain', $this->domain)
->first();
if ($findMainDomainSSLCertificate) {
$findDomainSSLCertificate = $findMainDomainSSLCertificate;
} else {
$findDomainSSLCertificateWildcard = \App\Models\DomainSslCertificate::where('domain', '*.' . $this->domain)
->where('is_wildcard', 1)
->first();
if ($findDomainSSLCertificateWildcard) {
$findDomainSSLCertificate = $findDomainSSLCertificateWildcard;
} else {
$findMainDomainWildcardSSLCertificate = \App\Models\DomainSslCertificate::where('domain', '*.'.$catchMainDomain)
->first();
if ($findMainDomainWildcardSSLCertificate) {
$findDomainSSLCertificate = $findMainDomainWildcardSSLCertificate;
}
}
}
if ($findDomainSSLCertificate) {
$sslCertificateFile = $this->home_root . '/certs/' . $this->domain . '/public/cert.pem';
$sslCertificateKeyFile = $this->home_root . '/certs/' . $this->domain . '/private/key.private.pem';
$sslCertificateChainFile = $this->home_root . '/certs/' . $this->domain . '/public/fullchain.pem';
if (!empty($findDomainSSLCertificate->certificate)) {
if (!is_dir($this->home_root . '/certs/' . $this->domain . '/public')) {
mkdir($this->home_root . '/certs/' . $this->domain . '/public', 0755, true);
}
file_put_contents($sslCertificateFile, $findDomainSSLCertificate->certificate);
}
if (!empty($findDomainSSLCertificate->private_key)) {
if (!is_dir($this->home_root . '/certs/' . $this->domain . '/private')) {
mkdir($this->home_root . '/certs/' . $this->domain . '/private', 0755, true);
}
file_put_contents($sslCertificateKeyFile, $findDomainSSLCertificate->private_key);
}
if (!empty($findDomainSSLCertificate->certificate_chain)) {
if (!is_dir($this->home_root . '/certs/' . $this->domain . '/public')) {
mkdir($this->home_root . '/certs/' . $this->domain . '/public', 0755, true);
}
file_put_contents($sslCertificateChainFile, $findDomainSSLCertificate->certificate_chain);
}
$apacheVirtualHostBuilder->setPort(443);
$apacheVirtualHostBuilder->setSSLCertificateFile($sslCertificateFile);
$apacheVirtualHostBuilder->setSSLCertificateKeyFile($sslCertificateKeyFile);
$apacheVirtualHostBuilder->setSSLCertificateChainFile($sslCertificateChainFile);
$apacheBaseConfigWithSSL = $apacheVirtualHostBuilder->buildConfig();
if (!empty($apacheBaseConfigWithSSL)) {
// Add SSL options conf file
$apache2SSLOptionsSample = view('actions.samples.ubuntu.apache2-ssl-options-conf')->render();
$apache2SSLOptionsFilePath = '/etc/apache2/phyre/options-ssl-apache.conf';
if (!file_exists($apache2SSLOptionsFilePath)) {
if (!is_dir('/etc/apache2/phyre')) {
mkdir('/etc/apache2/phyre');
}
file_put_contents($apache2SSLOptionsFilePath, $apache2SSLOptionsSample);
}
file_put_contents('/etc/apache2/sites-available/'.$this->domain.'-ssl.conf', $apacheBaseConfigWithSSL);
2024-05-02 08:16:24 +00:00
if (!is_link('/etc/apache2/sites-enabled/' . $this->domain . '-ssl.conf')) {
shell_exec('ln -s /etc/apache2/sites-available/' . $this->domain . '-ssl.conf /etc/apache2/sites-enabled/' . $this->domain . '-ssl.conf');
}
2024-04-22 11:14:05 +00:00
}
}
2024-04-29 08:55:56 +00:00
// Reload apache
if ($reloadApache) {
shell_exec('systemctl reload apache2');
}
2024-04-22 11:14:05 +00:00
}
}