Compare commits

..

No commits in common. "main" and "0.1.5" have entirely different histories.
main ... 0.1.5

74 changed files with 2046 additions and 10355 deletions

View file

@ -1,99 +1,13 @@
# --------------------------------------------------
# 1) Base Image
# --------------------------------------------------
FROM ubuntu:24.04
# syntax=docker/dockerfile:1
# So apt doesn't prompt us
ENV DEBIAN_FRONTEND=noninteractive
FROM ubuntu:22.04 AS production
# --------------------------------------------------
# 2) Install base dependencies
# --------------------------------------------------
RUN apt-get update && \
apt-get install -y --no-install-recommends \
ca-certificates \
wget \
curl \
netcat \
mysql-client \
unzip \
gnupg2 \
lsb-release \
apt-transport-https \
software-properties-common \
libpng-dev \
libwebp-dev \
libjpeg-turbo8 \
libfreetype6 \
supervisor && \
rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -yq wget
RUN ls -la
RUN wget https://raw.githubusercontent.com/PhyreApps/PhyrePanel/main/installers/install.sh -O phyre-install.sh
RUN chmod +x phyre-install.sh
RUN ./phyre-install.sh
# --------------------------------------------------
# 3) Install Phyre .deb packages
# --------------------------------------------------
# 3.1 - Add any system libs needed by Phyre (from your script):
RUN apt-get update && \
apt-get install -y --no-install-recommends \
openssl \
libonig-dev \
libzip-dev \
libcurl4-openssl-dev \
libsodium23 \
libpq5 \
libssl-dev \
zlib1g-dev && \
rm -rf /var/lib/apt/lists/*
COPY entrypoint.sh /usr/local/phyre/entrypoint.sh
WORKDIR /phyre/install
# 3.2 - Install Phyre PHP
RUN wget -q https://github.com/PhyreApps/PhyrePanelPHP/raw/main/compilators/debian/php/dist/phyre-php-8.2.0-ubuntu-22.04.deb && \
dpkg -i phyre-php-8.2.0-ubuntu-22.04.deb || (apt-get install -f -y && dpkg -i phyre-php-8.2.0-ubuntu-22.04.deb) && \
rm -f phyre-php-8.2.0-ubuntu-22.04.deb
# 3.3 - Install Phyre NGINX
RUN wget -q https://github.com/PhyreApps/PhyrePanelNGINX/raw/main/compilators/debian/nginx/dist/phyre-nginx-1.24.0-ubuntu-22.04.deb && \
dpkg -i phyre-nginx-1.24.0-ubuntu-22.04.deb || (apt-get install -f -y && dpkg -i phyre-nginx-1.24.0-ubuntu-22.04.deb) && \
rm -f phyre-nginx-1.24.0-ubuntu-22.04.deb && \
ln -s /usr/local/phyre/nginx/sbin/phyre-nginx /usr/local/phyre/nginx/sbin/nginx
# --------------------------------------------------
# 4) Symlink & SSL setup
# --------------------------------------------------
RUN ln -s /usr/local/phyre/php/bin/php /usr/bin/phyre-php
RUN mkdir -p /usr/local/phyre/ssl && \
wget -q https://raw.githubusercontent.com/PhyreApps/PhyrePanel/refs/heads/main/web/server/ssl/phyre.crt -O /usr/local/phyre/ssl/phyre.crt && \
wget -q https://raw.githubusercontent.com/PhyreApps/PhyrePanel/refs/heads/main/web/server/ssl/phyre.key -O /usr/local/phyre/ssl/phyre.key && \
chmod 644 /usr/local/phyre/ssl/phyre.crt && \
chmod 600 /usr/local/phyre/ssl/phyre.key
# --------------------------------------------------
# 5) Download Phyre Web Panel
# --------------------------------------------------
RUN wget -q https://github.com/PhyreApps/PhyrePanelWebCompiledVersions/raw/main/phyre-web-panel.zip && \
unzip -qq -o phyre-web-panel.zip -d /usr/local/phyre/web && \
rm -rf phyre-web-panel.zip
# --------------------------------------------------
# 6) Add a custom entrypoint script
# that will configure Phyre and run Nginx in foreground
# --------------------------------------------------
WORKDIR /usr/local/phyre/web
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
# Supervisord config (optional if you want to manage multiple processes)
# (But here we can simply run Phyre Nginx in the foreground)
#COPY supervisord.conf /etc/supervisor/conf.d/phyre-supervisor.conf
# Expose HTTP (80) and HTTPS (8443)
EXPOSE 80 8443
# --------------------------------------------------
# 7) Set up final Docker config
# --------------------------------------------------
# We'll run our entrypoint which configures the panel, then runs Nginx
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["phyre-php", "--version"]
ENTRYPOINT ["sh","/usr/local/phyre/entrypoint.sh"]

View file

@ -1,46 +0,0 @@
version: '3.8'
services:
db:
image: mysql:8.0
container_name: phyre-db
environment:
MYSQL_ROOT_PASSWORD: exampleRootPass
MYSQL_DATABASE: phyrepanel
MYSQL_USER: phyre
MYSQL_PASSWORD: examplePhyrePass
volumes:
- db_data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- phyre_net
phyre-app:
build: .
container_name: phyre-app
depends_on:
- db
ports:
- "8443:8443"
- "8080:80"
environment:
# These environment variables are used by our entrypoint
DB_HOST: db
DB_PORT: 3306
DB_DATABASE: phyrepanel
DB_USERNAME: phyre
DB_PASSWORD: examplePhyrePass
# Additional app settings
APP_ENV: local
APP_URL: "https://localhost:8443"
APP_NAME: PhyrePanel
networks:
- phyre_net
volumes:
db_data:
networks:
phyre_net:
driver: bridge

View file

@ -1,33 +1,4 @@
#!/usr/bin/env bash
set -e
service mysql start
service phyre start
# Wait for MySQL to be ready
echo "Waiting for database at $DB_HOST:$DB_PORT..."
while ! nc -z $DB_HOST $DB_PORT; do
sleep 2
done
echo "Database is up!"
# Configure environment variables
phyre-php artisan phyre:set-ini-settings DB_DATABASE "$DB_DATABASE"
phyre-php artisan phyre:set-ini-settings DB_USERNAME "$DB_USERNAME"
phyre-php artisan phyre:set-ini-settings DB_PASSWORD "$DB_PASSWORD"
phyre-php artisan phyre:set-ini-settings DB_HOST "$DB_HOST"
phyre-php artisan phyre:set-ini-settings DB_CONNECTION "mysql"
phyre-php artisan phyre:set-ini-settings APP_ENV "$APP_ENV"
phyre-php artisan phyre:set-ini-settings APP_URL "$APP_URL"
phyre-php artisan phyre:set-ini-settings APP_NAME "$APP_NAME"
# Generate keys, migrate, and seed
phyre-php artisan phyre:key-generate
phyre-php artisan migrate --force
phyre-php artisan db:seed --force
# Start Nginx in foreground
echo "Starting Nginx..."
exec /usr/sbin/service phyre start && /usr/local/phyre/nginx/sbin/nginx -g "daemon off;"
#exec /usr/sbin/service phyre start
# Start Supervisor to manage all processes
#echo "Starting Supervisor to manage processes..."
#exec /usr/bin/supervisord -c /etc/supervisor/conf.d/phyre-supervisor.conf
tail -f /dev/null

View file

@ -1,25 +0,0 @@
[supervisord]
nodaemon=true
logfile=/var/log/supervisord.log
pidfile=/var/run/supervisord.pid
[program:php-fpm]
command=/bin/bash -c 'if ! ps aux | grep "[p]hp-fpm: master process" > /dev/null; then /usr/local/phyre/php/sbin/phyre-php-fpm --nodaemonize; fi'
autostart=true
autorestart=true
stdout_logfile=/var/log/php-fpm.log
stderr_logfile=/var/log/php-fpm.err.log
[program:phyre]
command=/bin/bash -c 'while ! mysqladmin ping -h "$DB_HOST" --silent; do sleep 2; done; if ! ps aux | grep "[s]ervice phyre" > /dev/null; then /usr/sbin/service phyre start; fi'
autostart=true
autorestart=true
stdout_logfile=/var/log/phyre.log
stderr_logfile=/var/log/phyre.err.log
[program:phyre-nginx]
command=/bin/bash -c 'if ! ps aux | grep "[p]hyre-nginx" > /dev/null; then /usr/local/phyre/nginx/sbin/phyre-nginx -g "daemon off;"; fi'
autostart=true
autorestart=true
stdout_logfile=/var/log/phyre-nginx.log
stderr_logfile=/var/log/phyre-nginx.err.log

View file

@ -11,12 +11,12 @@ cd /usr/local/phyre/web
mysql -uroot -proot <<MYSQL_SCRIPT
SET GLOBAL validate_password.policy = LOW;
SET GLOBAL validate_password.length = 6;
SET GLOBAL validate_password.mixed_case_count = 0;
SET GLOBAL validate_password.number_count = 0;
SET GLOBAL validate_password.special_char_count = 0;
FLUSH PRIVILEGES;
SET GLOBAL validate_password.policy = LOW;
SET GLOBAL validate_password.length = 6;
SET GLOBAL validate_password.mixed_case_count = 0;
SET GLOBAL validate_password.number_count = 0;
SET GLOBAL validate_password.special_char_count = 0;
FLUSH PRIVILEGES;
MYSQL_SCRIPT
# Create MySQL user

View file

@ -0,0 +1,180 @@
#!/bin/bash
INSTALL_DIR="/phyre/install"
apt-get update && apt-get install ca-certificates
mkdir -p $INSTALL_DIR
cd $INSTALL_DIR
DEPENDENCIES_LIST=(
"openssl"
"jq"
"curl"
"wget"
"unzip"
"zip"
"tar"
"mysql-common"
"mysql-server"
"mysql-client"
"lsb-release"
"gnupg2"
"ca-certificates"
"apt-transport-https"
"software-properties-common"
"supervisor"
"libonig-dev"
"libzip-dev"
"libcurl4-openssl-dev"
"libsodium23"
"libpq5"
"apache2"
"libapache2-mod-ruid2"
"libapache2-mod-php"
"libssl-dev"
"zlib1g-dev"
)
# Check if the dependencies are installed
for DEPENDENCY in "${DEPENDENCIES_LIST[@]}"; do
apt install -yq $DEPENDENCY
done
# Start MySQL
service mysql start
mkdir -p /usr/local/phyre/ssl
wget https://raw.githubusercontent.com/PhyreApps/PhyrePanel/refs/heads/main/web/server/ssl/phyre.crt -O /usr/local/phyre/ssl/phyre.crt
wget https://raw.githubusercontent.com/PhyreApps/PhyrePanel/refs/heads/main/web/server/ssl/phyre.key -O /usr/local/phyre/ssl/phyre.key
sudo chmod 644 /usr/local/phyre/ssl/phyre.crt
sudo chmod 600 /usr/local/phyre/ssl/phyre.key
wget https://raw.githubusercontent.com/PhyreApps/PhyrePanel/main/installers/ubuntu-20.04/greeting.sh -O /etc/profile.d/phyre-greeting.sh
# Install PHYRE PHP
wget https://github.com/PhyreApps/PhyrePanelPHP/raw/main/compilators/debian/php/dist/phyre-php-8.2.0-ubuntu-20.04.deb
dpkg -i phyre-php-8.2.0-ubuntu-20.04.deb
# Install PHYRE NGINX
wget https://github.com/PhyreApps/PhyrePanelNGINX/raw/main/compilators/debian/nginx/dist/phyre-nginx-1.24.0-ubuntu-20.04.deb
dpkg -i phyre-nginx-1.24.0-ubuntu-20.04.deb
PHYRE_PHP=/usr/local/phyre/php/bin/php
ln -s $PHYRE_PHP /usr/bin/phyre-php
#!/bin/bash
HOSTNAME=$(hostname)
IP_ADDRESS=$(hostname -I | cut -d " " -f 1)
DISTRO_VERSION=$(cat /etc/os-release | grep -w "VERSION_ID" | cut -d "=" -f 2)
DISTRO_VERSION=${DISTRO_VERSION//\"/} # Remove quotes from version string
DISTRO_NAME=$(cat /etc/os-release | grep -w "NAME" | cut -d "=" -f 2)
DISTRO_NAME=${DISTRO_NAME//\"/} # Remove quotes from name string
LOG_JSON='{"os": "'$DISTRO_NAME-$DISTRO_VERSION'", "host_name": "'$HOSTNAME'", "ip": "'$IP_ADDRESS'"}'
curl -s https://phyrepanel.com/api/phyre-installation-log -X POST -H "Content-Type: application/json" -d "$LOG_JSON"
#!/bin/bash
wget https://github.com/PhyreApps/PhyrePanelWebCompiledVersions/raw/main/phyre-web-panel.zip
unzip -qq -o phyre-web-panel.zip -d /usr/local/phyre/web
rm -rf phyre-web-panel.zip
chmod 711 /home
chmod -R 750 /usr/local/phyre
#!/bin/bash
# Check dir exists
if [ ! -d "/usr/local/phyre/web" ]; then
echo "PhyrePanel directory not found."
return 1
fi
# Go to web directory
cd /usr/local/phyre/web
mysql -uroot -proot <<MYSQL_SCRIPT
SET GLOBAL validate_password.policy = LOW;
SET GLOBAL validate_password.length = 6;
SET GLOBAL validate_password.mixed_case_count = 0;
SET GLOBAL validate_password.number_count = 0;
SET GLOBAL validate_password.special_char_count = 0;
FLUSH PRIVILEGES;
MYSQL_SCRIPT
# Create MySQL user
MYSQL_PHYRE_ROOT_USERNAME="phyre"
MYSQL_PHYRE_ROOT_PASSWORD="$(tr -dc a-za-z0-9 </dev/urandom | head -c 32; echo)"
mysql -uroot -proot <<MYSQL_SCRIPT
CREATE USER '$MYSQL_PHYRE_ROOT_USERNAME'@'%' IDENTIFIED BY '$MYSQL_PHYRE_ROOT_PASSWORD';
GRANT ALL PRIVILEGES ON *.* TO '$MYSQL_PHYRE_ROOT_USERNAME'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
MYSQL_SCRIPT
# Create database
PHYRE_PANEL_DB_PASSWORD="$(tr -dc a-za-z0-9 </dev/urandom | head -c 32; echo)"
PHYRE_PANEL_DB_NAME="phyre$(tr -dc a-za-z0-9 </dev/urandom | head -c 13; echo)"
PHYRE_PANEL_DB_USER="phyre$(tr -dc a-za-z0-9 </dev/urandom | head -c 13; echo)"
mysql -uroot -proot <<MYSQL_SCRIPT
CREATE DATABASE $PHYRE_PANEL_DB_NAME;
CREATE USER '$PHYRE_PANEL_DB_USER'@'localhost' IDENTIFIED BY '$PHYRE_PANEL_DB_PASSWORD';
GRANT ALL PRIVILEGES ON $PHYRE_PANEL_DB_NAME.* TO '$PHYRE_PANEL_DB_USER'@'localhost';
FLUSH PRIVILEGES;
MYSQL_SCRIPT
mysql_secure_installation --use-default
# Change mysql root password
MYSQL_ROOT_PASSWORD="$(tr -dc a-za-z0-9 </dev/urandom | head -c 32; echo)"
mysql -uroot -proot <<MYSQL_SCRIPT
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password by '$MYSQL_ROOT_PASSWORD';
FLUSH PRIVILEGES;
MYSQL_SCRIPT
# Save mysql root password
echo "$MYSQL_ROOT_PASSWORD" > /root/.mysql_root_password
# Configure the application
phyre-php artisan phyre:set-ini-settings APP_ENV "local"
phyre-php artisan phyre:set-ini-settings APP_URL "127.0.0.1:8443"
phyre-php artisan phyre:set-ini-settings APP_NAME "PHYRE_PANEL"
phyre-php artisan phyre:set-ini-settings DB_DATABASE "$PHYRE_PANEL_DB_NAME"
phyre-php artisan phyre:set-ini-settings DB_USERNAME "$PHYRE_PANEL_DB_USER"
phyre-php artisan phyre:set-ini-settings DB_PASSWORD "$PHYRE_PANEL_DB_PASSWORD"
phyre-php artisan phyre:set-ini-settings DB_CONNECTION "mysql"
phyre-php artisan phyre:set-ini-settings MYSQL_ROOT_USERNAME "$MYSQL_PHYRE_ROOT_USERNAME"
phyre-php artisan phyre:set-ini-settings MYSQL_ROOT_PASSWORD "$MYSQL_PHYRE_ROOT_PASSWORD"
phyre-php artisan phyre:key-generate
phyre-php artisan migrate
phyre-php artisan db:seed
phyre-php artisan phyre:set-ini-settings APP_ENV "production"
chmod -R o+w /usr/local/phyre/web/storage/
chmod -R o+w /usr/local/phyre/web/bootstrap/cache/
service phyre start
CURRENT_IP=$(hostname -I | awk '{print $1}')
echo "PhyrePanel downloaded successfully."
# Parse argument --dont-ask
if [ "$1" == "--dont-ask" ]; then
echo "PhyrePanel is now available at https://$CURRENT_IP:8443"
exit 0
else
phyre-php artisan phyre:install-apache
phyre-php artisan phyre:setup-master-domain-ssl
fi

View file

@ -0,0 +1,182 @@
#!/bin/bash
INSTALL_DIR="/phyre/install"
apt-get update && apt-get install ca-certificates
mkdir -p $INSTALL_DIR
cd $INSTALL_DIR
DEPENDENCIES_LIST=(
"openssl"
"jq"
"curl"
"wget"
"unzip"
"zip"
"tar"
"mysql-common"
"mysql-server"
"mysql-client"
"lsb-release"
"gnupg2"
"ca-certificates"
"apt-transport-https"
"software-properties-common"
"supervisor"
"libonig-dev"
"libzip-dev"
"libcurl4-openssl-dev"
"libsodium23"
"libpq5"
"apache2"
"libapache2-mod-ruid2"
"libapache2-mod-php"
"libssl-dev"
"zlib1g-dev"
)
# Check if the dependencies are installed
for DEPENDENCY in "${DEPENDENCIES_LIST[@]}"; do
apt install -yq $DEPENDENCY
done
# Start MySQL
service mysql start
mkdir -p /usr/local/phyre/ssl
wget https://raw.githubusercontent.com/PhyreApps/PhyrePanel/refs/heads/main/web/server/ssl/phyre.crt -O /usr/local/phyre/ssl/phyre.crt
wget https://raw.githubusercontent.com/PhyreApps/PhyrePanel/refs/heads/main/web/server/ssl/phyre.key -O /usr/local/phyre/ssl/phyre.key
sudo chmod 644 /usr/local/phyre/ssl/phyre.crt
sudo chmod 600 /usr/local/phyre/ssl/phyre.key
wget https://raw.githubusercontent.com/PhyreApps/PhyrePanel/main/installers/ubuntu-22.04/greeting.sh -O /etc/profile.d/phyre-greeting.sh
# Install PHYRE PHP
wget https://github.com/PhyreApps/PhyrePanelPHP/raw/main/compilators/debian/php/dist/phyre-php-8.2.0-ubuntu-22.04.deb
dpkg -i phyre-php-8.2.0-ubuntu-22.04.deb
# Install PHYRE NGINX
wget https://github.com/PhyreApps/PhyrePanelNGINX/raw/main/compilators/debian/nginx/dist/phyre-nginx-1.24.0-ubuntu-22.04.deb
dpkg -i phyre-nginx-1.24.0-ubuntu-22.04.deb
PHYRE_PHP=/usr/local/phyre/php/bin/php
ln -s $PHYRE_PHP /usr/bin/phyre-php
curl -s https://phyrepanel.com/api/phyre-installation-log -X POST -H "Content-Type: application/json" -d '{"os": "ubuntu-22.04"}'
#!/bin/bash
HOSTNAME=$(hostname)
IP_ADDRESS=$(hostname -I | cut -d " " -f 1)
DISTRO_VERSION=$(cat /etc/os-release | grep -w "VERSION_ID" | cut -d "=" -f 2)
DISTRO_VERSION=${DISTRO_VERSION//\"/} # Remove quotes from version string
DISTRO_NAME=$(cat /etc/os-release | grep -w "NAME" | cut -d "=" -f 2)
DISTRO_NAME=${DISTRO_NAME//\"/} # Remove quotes from name string
LOG_JSON='{"os": "'$DISTRO_NAME-$DISTRO_VERSION'", "host_name": "'$HOSTNAME'", "ip": "'$IP_ADDRESS'"}'
curl -s https://phyrepanel.com/api/phyre-installation-log -X POST -H "Content-Type: application/json" -d "$LOG_JSON"
#!/bin/bash
wget https://github.com/PhyreApps/PhyrePanelWebCompiledVersions/raw/main/phyre-web-panel.zip
unzip -qq -o phyre-web-panel.zip -d /usr/local/phyre/web
rm -rf phyre-web-panel.zip
chmod 711 /home
chmod -R 750 /usr/local/phyre
#!/bin/bash
# Check dir exists
if [ ! -d "/usr/local/phyre/web" ]; then
echo "PhyrePanel directory not found."
return 1
fi
# Go to web directory
cd /usr/local/phyre/web
mysql -uroot -proot <<MYSQL_SCRIPT
SET GLOBAL validate_password.policy = LOW;
SET GLOBAL validate_password.length = 6;
SET GLOBAL validate_password.mixed_case_count = 0;
SET GLOBAL validate_password.number_count = 0;
SET GLOBAL validate_password.special_char_count = 0;
FLUSH PRIVILEGES;
MYSQL_SCRIPT
# Create MySQL user
MYSQL_PHYRE_ROOT_USERNAME="phyre"
MYSQL_PHYRE_ROOT_PASSWORD="$(tr -dc a-za-z0-9 </dev/urandom | head -c 32; echo)"
mysql -uroot -proot <<MYSQL_SCRIPT
CREATE USER '$MYSQL_PHYRE_ROOT_USERNAME'@'%' IDENTIFIED BY '$MYSQL_PHYRE_ROOT_PASSWORD';
GRANT ALL PRIVILEGES ON *.* TO '$MYSQL_PHYRE_ROOT_USERNAME'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
MYSQL_SCRIPT
# Create database
PHYRE_PANEL_DB_PASSWORD="$(tr -dc a-za-z0-9 </dev/urandom | head -c 32; echo)"
PHYRE_PANEL_DB_NAME="phyre$(tr -dc a-za-z0-9 </dev/urandom | head -c 13; echo)"
PHYRE_PANEL_DB_USER="phyre$(tr -dc a-za-z0-9 </dev/urandom | head -c 13; echo)"
mysql -uroot -proot <<MYSQL_SCRIPT
CREATE DATABASE $PHYRE_PANEL_DB_NAME;
CREATE USER '$PHYRE_PANEL_DB_USER'@'localhost' IDENTIFIED BY '$PHYRE_PANEL_DB_PASSWORD';
GRANT ALL PRIVILEGES ON $PHYRE_PANEL_DB_NAME.* TO '$PHYRE_PANEL_DB_USER'@'localhost';
FLUSH PRIVILEGES;
MYSQL_SCRIPT
mysql_secure_installation --use-default
# Change mysql root password
MYSQL_ROOT_PASSWORD="$(tr -dc a-za-z0-9 </dev/urandom | head -c 32; echo)"
mysql -uroot -proot <<MYSQL_SCRIPT
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password by '$MYSQL_ROOT_PASSWORD';
FLUSH PRIVILEGES;
MYSQL_SCRIPT
# Save mysql root password
echo "$MYSQL_ROOT_PASSWORD" > /root/.mysql_root_password
# Configure the application
phyre-php artisan phyre:set-ini-settings APP_ENV "local"
phyre-php artisan phyre:set-ini-settings APP_URL "127.0.0.1:8443"
phyre-php artisan phyre:set-ini-settings APP_NAME "PHYRE_PANEL"
phyre-php artisan phyre:set-ini-settings DB_DATABASE "$PHYRE_PANEL_DB_NAME"
phyre-php artisan phyre:set-ini-settings DB_USERNAME "$PHYRE_PANEL_DB_USER"
phyre-php artisan phyre:set-ini-settings DB_PASSWORD "$PHYRE_PANEL_DB_PASSWORD"
phyre-php artisan phyre:set-ini-settings DB_CONNECTION "mysql"
phyre-php artisan phyre:set-ini-settings MYSQL_ROOT_USERNAME "$MYSQL_PHYRE_ROOT_USERNAME"
phyre-php artisan phyre:set-ini-settings MYSQL_ROOT_PASSWORD "$MYSQL_PHYRE_ROOT_PASSWORD"
phyre-php artisan phyre:key-generate
phyre-php artisan migrate
phyre-php artisan db:seed
phyre-php artisan phyre:set-ini-settings APP_ENV "production"
chmod -R o+w /usr/local/phyre/web/storage/
chmod -R o+w /usr/local/phyre/web/bootstrap/cache/
service phyre start
CURRENT_IP=$(hostname -I | awk '{print $1}')
echo "PhyrePanel downloaded successfully."
# Parse argument --dont-ask
if [ "$1" == "--dont-ask" ]; then
echo "PhyrePanel is now available at https://$CURRENT_IP:8443"
exit 0
else
phyre-php artisan phyre:install-apache
phyre-php artisan phyre:setup-master-domain-ssl
fi

View file

@ -102,12 +102,12 @@ cd /usr/local/phyre/web
mysql -uroot -proot <<MYSQL_SCRIPT
SET GLOBAL validate_password.policy = LOW;
SET GLOBAL validate_password.length = 6;
SET GLOBAL validate_password.mixed_case_count = 0;
SET GLOBAL validate_password.number_count = 0;
SET GLOBAL validate_password.special_char_count = 0;
FLUSH PRIVILEGES;
SET GLOBAL validate_password.policy = LOW;
SET GLOBAL validate_password.length = 6;
SET GLOBAL validate_password.mixed_case_count = 0;
SET GLOBAL validate_password.number_count = 0;
SET GLOBAL validate_password.special_char_count = 0;
FLUSH PRIVILEGES;
MYSQL_SCRIPT
# Create MySQL user

View file

@ -1 +1 @@
0.1.7
0.1.4

View file

@ -4,7 +4,7 @@
"description": "",
"keywords": [],
"priority": 0,
"logoIcon": "Modules/Email/resources/assets/email-svg/logo.svg",
"logoIcon": "email-logo",
"category": "DevOps",
"adminUrl": "/admin/email",
"providers": [

View file

@ -1,3 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="50px" height="50px" viewBox="0 0 20 20">
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 20 20">
<path fill="currentColor" d="M18 2a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4c0-1.1.9-2 2-2zm-4.37 9.1L20 16v-2l-5.12-3.9L20 6V4l-10 8L0 4v2l5.12 4.1L0 14v2l6.37-4.9L10 14z" />
</svg>

Before

Width:  |  Height:  |  Size: 284 B

After

Width:  |  Height:  |  Size: 280 B

View file

@ -18,7 +18,7 @@ class ListInstallations extends ListRecords
{
return [
// Actions\CreateAction::make(),
Actions\Action::make('Scan for installations')->action('scanForInstallations'),
// Actions\Action::make('Scan for installations')->action('scanForInstallations'),
];
}

View file

@ -1,44 +0,0 @@
<?php
namespace Modules\Microweber\Listeners;
use App\Events\DomainIsCreated;
use App\Events\DomainIsDeleted;
use App\Models\Database;
use App\Models\DatabaseUser;
use App\Models\Domain;
use App\Models\HostingPlan;
use App\Models\HostingSubscription;
use App\Services\HostingSubscriptionService;
use App\SupportedApplicationTypes;
use Illuminate\Support\Str;
use MicroweberPackages\SharedServerScripts\MicroweberWhitelabelSettingsUpdater;
use MicroweberPackages\SharedServerScripts\MicroweberWhitelabelWebsiteApply;
use Modules\Microweber\App\Actions\MicroweberScanner;
use Modules\Microweber\App\Models\MicroweberInstallation;
class DomainIsDeletedListener
{
/**
* Create the event listener.
*/
public function __construct()
{
//
}
/**
* Handle the event.
*/
public function handle(DomainIsDeleted $event): void
{
try {
$newMwScan = new MicroweberScanner();
$newMwScan->handle();
} catch (\Exception $e) {
\Log::error($e->getMessage());
}
}
}

View file

@ -4,7 +4,7 @@
"description": "",
"keywords": [],
"priority": 0,
"logoIcon": "Modules/Microweber/resources/assets/mw-svg/mw_logo_small_white.svg",
"logoIcon": "mw-mw_logo_small_white",
"category": "Content Management",
"adminUrl": "/admin/microweber/installations",
"providers": [

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" width="50px" height="50px" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
<path fill="currentColor" d="M47.5,37.9C47.5,37.9,47.5,37.9,47.5,37.9c-0.4,0.8-0.9,1.5-1.5,2.2c0,0,0,0,0,0c-1.1,1.3-2.5,2.2-4.2,2.7 L25.2,48c-0.7,0.2-1.5,0.1-2.2-0.3c-0.6-0.4-1.1-1.1-1.1-1.9l-3-32.8l0.7,0.1l1.5,0.1l3,0.2c0.9,0.1,1.7,0.8,1.8,1.6l3.1,24.1 l6.3-1.4L31.6,14l0.7,0.1l1.1,0.1l2.1,0.2c0.7,0.1,1.3,0.7,1.5,1.3l3.7,20.8l4.8-1.1l-4.2-20.7c-0.5-2.6-2.9-4.9-5.4-5.2L13.6,6.5 c-0.8-0.1-1.5,0.1-2.1,0.7c-0.6,0.5-0.9,1.3-0.8,2l2,37.2l0.1,2.1l0,0.8C6.4,47.9,1.6,42.7,1.6,35.9L1.4,11.7c0-2.9,1.1-5.4,3-7.1 C6.1,3,8.4,1.9,11,1.4c2.1-0.4,4.4-0.4,6.7,0.1l17.3,3.4c4.9,0.9,9.3,5.4,10.3,10.2l3.1,14.3C49.2,32.3,48.8,35.4,47.5,37.9z"/>
</svg>

Before

Width:  |  Height:  |  Size: 1,013 B

After

Width:  |  Height:  |  Size: 985 B

View file

@ -1,114 +0,0 @@
<?php
namespace Modules\SSLManager\App\Console;
use App\Jobs\ApacheBuild;
use App\Models\CronJob;
use App\Models\Domain;
use Illuminate\Console\Command;
use Modules\SSLManager\App\Jobs\SecureDomain;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class RenewSSL extends Command
{
/**
* The name and signature of the console command.
*/
protected $signature = 'ssl-manager:renew-ssl';
/**
* The console command description.
*/
protected $description = 'Renew SSL certificates';
/**
* Create a new command instance.
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*/
public function handle()
{
$this->_checkForAutoRenewalCron();
$getDomains = Domain::where('status', Domain::STATUS_ACTIVE)
->get();
if ($getDomains->count() > 0) {
foreach ($getDomains as $domain) {
$checkDomainStatus = $this->_checkForSSL($domain->domain);
if ($checkDomainStatus) {
$this->info('SSL certificate for ' . $domain->domain . ' is valid');
} else {
$this->info('SSL certificate for ' . $domain->domain . ' is expired');
try {
$this->_renewSSL($domain);
} catch (\Exception $e) {
$this->error($e->getMessage());
}
}
}
// Rebuild Apache configuration
$this->info('Rebuilding Apache configuration');
$apacheBuild = new ApacheBuild(true);
$apacheBuild->handle();
}
}
private function _renewSSL($domain)
{
// Renew SSL
$this->info('Renewing SSL certificate for ' . $domain->domain);
$run = new SecureDomain($domain->id);
$run->handle();
}
private function _checkForSSL($domain)
{
// Check with CURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://" . $domain);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
$data = curl_exec($ch);
$sslInfo = curl_getinfo($ch);
if ($sslInfo['http_code'] == 200) {
return true;
} else {
return false;
}
}
public function _checkForAutoRenewalCron()
{
$cronJobCommand = 'phyre-php /usr/local/phyre/web/artisan ssl-manager:renew-ssl';
$findCronJob = CronJob::where('command', $cronJobCommand)->first();
if (! $findCronJob) {
$cronJob = new CronJob();
$cronJob->schedule = '0 0 * * *';
$cronJob->command = $cronJobCommand;
$cronJob->user = 'root';
$cronJob->save();
}
}
}

View file

@ -21,13 +21,13 @@ use Filament\Notifications\Notification;
class WildcardIssuer extends Page
{
protected static ?string $navigationGroup = 'SSL Manager';
protected static ?string $navigationGroup = 'SSL Manager';
protected static ?string $navigationIcon = null;
protected static ?int $navigationSort = 2;
protected static ?int $navigationSort = 2;
public $poolingInstallLog = true;
public $poolingInstallLog = true;
public $installLog = '';
public $installLogFilePath = '/var/www/acme-wildcard-install.log';
public $installInstructions = [];
@ -73,7 +73,7 @@ class WildcardIssuer extends Page
public function requestCertificates() {
$wildcardDomain = $this->wildcardDomain;
$wildcardDomain = str_replace('*.', '', $wildcardDomain);
$wildcardDomain = str_replace('*.', '', $wildcardDomain);
if (file_exists($this->installLogFilePath)) {
unlink($this->installLogFilePath);
@ -93,7 +93,7 @@ class WildcardIssuer extends Page
public function installCertificates()
{
$wildcardDomain = $this->wildcardDomain;
$wildcardDomain = str_replace('*.', '', $wildcardDomain);
@ -159,7 +159,7 @@ class WildcardIssuer extends Page
$acmeChallangeDomain = str_replace('Domain: ', '', $acmeChallangeDomain);
$acmeChallangeTxtValue = str_replace('TXT value: ', '', $acmeChallangeTxtValue);
$this->installInstructions = [
'acmeChallangeDomain' => $acmeChallangeDomain,
'acmeChallangeDomain' => $acmeChallangeDomain,
'acmeChallangeTxtValue' => $acmeChallangeTxtValue,
];
$this->poolingInstallLog = false;
@ -199,7 +199,7 @@ class WildcardIssuer extends Page
->default(setting('general.master_email'))
->helperText('Email address for notifications')
->placeholder('master@example.com'),
])->afterValidation(function () {
if (file_exists($this->installLogFilePath)) {

View file

@ -46,24 +46,15 @@ class CertificateResource extends Resource
->sortable(),
TextColumn::make('is_active')
->badge()
->formatStateUsing(function ($state) {
return $state ? 'Active' : 'Inactive';
})
->searchable()
->sortable(),
TextColumn::make('is_wildcard')
->badge()
->formatStateUsing(function ($state) {
return $state ? 'Wildcard' : 'Standard';
})
->searchable()
->sortable(),
TextColumn::make('provider')
->searchable()
->formatStateUsing(function ($state) {
return strtoupper($state);
})
->sortable(),
])
@ -71,13 +62,12 @@ class CertificateResource extends Resource
//
])
->actions([
Tables\Actions\DeleteAction::make(),
// Tables\Actions\EditAction::make(),
Tables\Actions\EditAction::make(),
])
->bulkActions([
// Tables\Actions\BulkActionGroup::make([
// Tables\Actions\DeleteBulkAction::make(),
// ]),
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
@ -92,8 +82,8 @@ class CertificateResource extends Resource
{
return [
'index' => Pages\ListCertificates::route('/'),
// 'create' => Pages\CreateCertificate::route('/create'),
// 'edit' => Pages\EditCertificate::route('/{record}/edit'),
'create' => Pages\CreateCertificate::route('/create'),
'edit' => Pages\EditCertificate::route('/{record}/edit'),
];
}
}

View file

@ -13,7 +13,7 @@ class ListCertificates extends ListRecords
protected function getHeaderActions(): array
{
return [
// Actions\CreateAction::make(),
Actions\CreateAction::make(),
];
}
}

View file

@ -1,131 +0,0 @@
<?php
namespace Modules\SSLManager\App\Jobs;
use App\Models\DomainSslCertificate;
use App\Settings;
class SecureDomain
{
public $domainId;
public function __construct($domainId)
{
$this->domainId = $domainId;
}
public function handle(): void
{
$findDomain = \App\Models\Domain::where('id', $this->domainId)->first();
if (!$findDomain) {
throw new \Exception('Domain not found');
}
$domainName = $findDomain->domain;
$domainName = trim($domainName);
$domainName = str_replace('www.', '', $domainName);
if (empty($domainName)) {
throw new \Exception('Domain name is empty');
}
$domainNameWww = 'www.' . $domainName;
$domainNameWww = str_replace('www.www.', 'www.', $domainNameWww);
$generalSettings = Settings::general();
$sslCertificateFilePath = '/etc/ssl-manager/domains/' . $domainName . '/cert.pem';
$sslCertificateKeyFilePath = '/etc/ssl-manager/domains/' . $domainName . '/privkey.pem';
$sslCertificateChainFilePath = '/etc/ssl-manager/domains/' . $domainName . '/fullchain.pem';
if (!is_dir('/etc/ssl-manager/domains/' . $domainName)) {
shell_exec('mkdir -p /etc/ssl-manager/domains/' . $domainName);
}
shell_exec('chmod +x /usr/local/phyre/web/Modules/SSLManager/shell/acme.sh');
$exec = shell_exec("bash /usr/local/phyre/web/Modules/SSLManager/shell/acme.sh --register-account -m " . $generalSettings['master_email'] . " --server letsencrypt");
$tmpFile = '/tmp/acme-sh-zerossl-http-secure-command-' . $findDomain->id . '.sh';
$certbotHttpSecureCommand = view('sslmanager::actions.acme-sh-http-secure-command', [
'domain' => $domainName,
'domainNameWww' => $domainNameWww,
'domainRoot' => $findDomain->domain_root,
'domainPublic' => $findDomain->domain_public,
'email' => $generalSettings['master_email'],
'country' => $generalSettings['master_country'],
'locality' => $generalSettings['master_locality'],
'organization' => $generalSettings['organization_name'],
])->render();
file_put_contents($tmpFile, $certbotHttpSecureCommand);
shell_exec('chmod +x ' . $tmpFile);
$exec = shell_exec("bash $tmpFile");
unlink($tmpFile);
//check file
$zerSslCert = '/root/.acme.sh/' . $domainName . '_ecc/' . $domainName . '.cer';
$zerSslCertKey = '/root/.acme.sh/' . $domainName . '_ecc/' . $domainName . '.key';
$zerSslCertIntermediate = '/root/.acme.sh/' . $domainName . '_ecc/ca.cer';
$zerSslCertFullChain = '/root/.acme.sh/' . $domainName . '_ecc/fullchain.cer';
if (!file_exists($zerSslCert)
|| !file_exists($zerSslCertKey)
|| !file_exists($zerSslCertFullChain)) {
// Cant get all certificates
throw new \Exception('Cant get certificates with ZeroSSL');
}
file_put_contents($sslCertificateFilePath, file_get_contents($zerSslCert));
file_put_contents($sslCertificateKeyFilePath, file_get_contents($zerSslCertKey));
file_put_contents($sslCertificateChainFilePath, file_get_contents($zerSslCertFullChain));
if (!file_exists($sslCertificateFilePath)
|| !file_exists($sslCertificateKeyFilePath)
|| !file_exists($sslCertificateChainFilePath)) {
// Cant get all certificates
throw new \Exception('Cant get all certificates');
}
$sslCertificateFileContent = file_get_contents($sslCertificateFilePath);
$sslCertificateKeyFileContent = file_get_contents($sslCertificateKeyFilePath);
$sslCertificateChainFileContent = file_get_contents($sslCertificateChainFilePath);
if (!empty($sslCertificateChainFileContent)) {
$validateCertificates['certificate'] = $sslCertificateFileContent;
}
if (!empty($sslCertificateKeyFileContent)) {
$validateCertificates['private_key'] = $sslCertificateKeyFileContent;
}
if (!empty($sslCertificateChainFileContent)) {
$validateCertificates['certificate_chain'] = $sslCertificateChainFileContent;
}
if (count($validateCertificates) !== 3) {
// Cant get all certificates
throw new \Exception('Cant get all certificates');
}
$websiteSslCertificate = DomainSslCertificate::where('domain', $findDomain->domain)->first();
if (!$websiteSslCertificate) {
$websiteSslCertificate = new DomainSslCertificate();
$websiteSslCertificate->domain = $findDomain->domain;
$websiteSslCertificate->certificate = $validateCertificates['certificate'];
$websiteSslCertificate->private_key = $validateCertificates['private_key'];
$websiteSslCertificate->certificate_chain = $validateCertificates['certificate_chain'];
$websiteSslCertificate->customer_id = $findDomain->customer_id;
$websiteSslCertificate->is_active = 1;
$websiteSslCertificate->is_wildcard = 0;
$websiteSslCertificate->is_auto_renew = 1;
}
$websiteSslCertificate->provider = 'ACME';
$websiteSslCertificate->save();
$findDomain->configureVirtualHost(true);
}
}

View file

@ -30,16 +30,16 @@ class SSLManagerServiceProvider extends ServiceProvider
*/
public function register(): void
{
// Register Phyre Icons set
$this->callAfterResolving(Factory::class, function (Factory $factory) {
$factory->add('ssl_manager', [
'path' => __DIR__ . '/../../resources/assets/ssl-manager-svg',
'prefix' => 'ssl_manager',
'prefix' => 'ssl_manager',
]);
});
$this->app->register(RouteServiceProvider::class);
$this->app->register(RouteServiceProvider::class);
}
@ -48,9 +48,7 @@ class SSLManagerServiceProvider extends ServiceProvider
*/
protected function registerCommands(): void
{
$this->commands([
\Modules\SSLManager\App\Console\RenewSSL::class,
]);
// $this->commands([]);
}
/**
@ -103,7 +101,6 @@ class SSLManagerServiceProvider extends ServiceProvider
$componentNamespace = str_replace('/', '\\', config('modules.namespace').'\\'.$this->moduleName.'\\'.config('modules.paths.generator.component-class.path'));
Blade::componentNamespace($componentNamespace, $this->moduleNameLower);
}
/**

View file

@ -4,11 +4,11 @@
"description": "",
"keywords": [],
"priority": 0,
"logoIcon": "/Modules/SSLManager/resources/assets/ssl-manager-svg/logo.svg",
"logoIcon": "ssl_manager-logo",
"category": "Security",
"adminUrl": "/admin/certificates",
"adminUrl": "/admin/ssl-manager/ssl-manager-certificates",
"providers": [
"Modules\\SSLManager\\App\\Providers\\SSLManagerServiceProvider"
],
"files": []
}
}

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="currentColor" width="60px" height="60px" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<svg fill="currentColor" width="800px" height="800px" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<path d="M24.26 32h-16.521c-0.708 0-1.281-0.573-1.281-1.281v-12.224c0-0.708 0.573-1.286 1.281-1.286h1.552v-1.974c0-3.698 3.010-6.708 6.708-6.708s6.708 3.010 6.708 6.708v1.974h1.552c0.708 0 1.281 0.578 1.281 1.286v12.224c0 0.708-0.573 1.281-1.281 1.281zM16.839 25.24c1.521-0.859 0.911-3.182-0.839-3.182-1.745 0.005-2.354 2.318-0.839 3.182v1.656c0 1.115 1.677 1.115 1.677 0zM13.141 17.208h5.724v-1.974c0-1.578-1.286-2.859-2.865-2.859s-2.859 1.281-2.859 2.859zM6.063 15.391h-3.984c-0.651 0-1.172-0.526-1.172-1.172s0.521-1.172 1.172-1.172h3.984c0.646 0 1.172 0.526 1.172 1.172s-0.526 1.172-1.172 1.172zM8.87 9.12c-0.271 0-0.531-0.094-0.74-0.271l-3.156-2.594c-0.5-0.406-0.568-1.146-0.156-1.646 0.406-0.5 1.146-0.573 1.646-0.161l3.156 2.594c0.849 0.698 0.349 2.078-0.75 2.073zM16 6.359c-0.646 0-1.172-0.526-1.172-1.172v-4.016c0-0.646 0.526-1.172 1.172-1.172s1.172 0.526 1.172 1.172v4.016c0 0.646-0.526 1.172-1.172 1.172zM23.13 9.12c-1.104 0-1.599-1.38-0.75-2.078l3.156-2.594c1.208-0.99 2.693 0.818 1.49 1.813l-3.156 2.594c-0.208 0.172-0.469 0.266-0.74 0.266zM29.922 15.391h-4.021c-0.651 0-1.172-0.526-1.172-1.172s0.521-1.172 1.172-1.172h4.021c0.651 0 1.172 0.526 1.172 1.172s-0.521 1.172-1.172 1.172z"/>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -1 +0,0 @@
/usr/local/phyre/web/Modules/SSLManager/shell/acme.sh --issue -d {{$domain}} -d www.{{$domain}} --webroot {{$domainPublic}} --server letsencrypt

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
"description": "",
"keywords": [],
"priority": 0,
"logoIcon": "Modules/Terminal/resources/assets/terminal-svg/logo.svg",
"logoIcon": "heroicon-o-command-line",
"category": "DevOps",
"adminUrl": "/admin/terminal",
"providers": [

View file

@ -1,120 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="50px" height="50px"
viewBox="0 0 30 30"
version="1.1"
id="svg822"
inkscape:version="0.92.4 (f8dce91, 2019-08-02)"
sodipodi:docname="terminal.svg">
<defs
id="defs816">
<inkscape:path-effect
only_selected="false"
apply_with_weight="true"
apply_no_weight="true"
helper_size="0"
steps="2"
weight="33.333333"
is_visible="true"
id="path-effect1025"
effect="bspline" />
<inkscape:path-effect
only_selected="false"
apply_with_weight="true"
apply_no_weight="true"
helper_size="0"
steps="2"
weight="33.333333"
is_visible="true"
id="path-effect1021"
effect="bspline" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="17.833333"
inkscape:cx="15.855957"
inkscape:cy="16.664315"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="px"
inkscape:window-width="1366"
inkscape:window-height="713"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
showguides="false"
inkscape:guide-bbox="true">
<sodipodi:guide
position="21.126168,22.794393"
orientation="1,0"
id="guide1575"
inkscape:locked="false" />
<sodipodi:guide
position="22.682243,23.285047"
orientation="1,0"
id="guide1635"
inkscape:locked="false" />
<sodipodi:guide
position="22.682243,7.6455921"
orientation="0,1"
id="guide1639"
inkscape:locked="false" />
<sodipodi:guide
position="18.859863,18.859863"
orientation="1,0"
id="guide1242"
inkscape:locked="false" />
<inkscape:grid
type="xygrid"
id="grid1103" />
</sodipodi:namedview>
<metadata
id="metadata819">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>
</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-289.0625)">
<ellipse
fill="currentColor"
cy="301.98773"
cx="16.607477"
id="circle863"
style="opacity:1;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
r="6" />
<path
fill="currentColor"
style="opacity:1;fill-opacity:1;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 5 3 C 3.892 3 3 3.892 3 5 L 3 25 C 3 26.108 3.892 27 5 27 L 25 27 C 26.108 27 27 26.108 27 25 L 27 5 C 27 3.892 26.108 3 25 3 L 5 3 z M 6.875 8.3964844 L 13.394531 12.421875 L 13.394531 14.056641 L 6.9257812 18.082031 L 6 16.734375 L 11.761719 13.248047 L 6 9.7949219 L 6.875 8.3964844 z M 15.578125 20.052734 L 24 20.052734 L 24 21.603516 L 15.578125 21.603516 L 15.578125 20.052734 z "
transform="translate(0,289.0625)"
id="rect901" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.7 KiB

View file

@ -79,8 +79,6 @@ class RunRepair extends Command
$this->fixApacheErrors();
echo shell_exec('phyre-php /usr/local/phyre/web/artisan ssl-manager:renew-ssl');
}
public function fixPhpMyAdmin()

View file

@ -73,11 +73,11 @@ class SetupMasterDomainSSL extends Command
file_put_contents('/var/www/html/index.html', view('actions/samples/apache/html/app-index')->render());
// Register ACME account
$acmeCommand = "bash /usr/local/phyre/web/Modules/SSLManager/shell/acme.sh --register-account -m $this->masterEmail";
$acmeCommand = "bash /usr/local/phyre/web/Modules/LetsEncrypt/shell/acme.sh --register-account -m $this->masterEmail";
$acmeCommand = shell_exec($acmeCommand);
// Issue SSL certificate
$acmeCommand = "bash /usr/local/phyre/web/Modules/SSLManager/shell/acme.sh --issue -d '$this->masterDomain' --webroot /var/www/html";
$acmeCommand = "bash /usr/local/phyre/web/Modules/LetsEncrypt/shell/acme.sh --issue -d '$this->masterDomain' --webroot /var/www/html";
$acmeCommand = shell_exec($acmeCommand);
$issued = false;

View file

@ -1,35 +0,0 @@
<?php
namespace App\Events;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class DomainIsDeleted
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $model;
/**
* Create a new event instance.
*/
public function __construct($model)
{
$this->model = $model;
}
/**
* Get the channels the event should broadcast on.
*
* @return array<int, \Illuminate\Broadcasting\Channel>
*/
public function broadcastOn(): array
{
return [
new PrivateChannel('channel-name'),
];
}
}

View file

@ -1,251 +0,0 @@
<?php
namespace App\Filament\Pages;
use App\Jobs\ApacheBuild;
use App\Models\Domain;
use App\Models\HostingSubscription;
use Carbon\Carbon;
use Filament\Actions\Action;
use Filament\Forms\Components\Checkbox;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Wizard;
use Filament\Forms\Form;
use Filament\Forms\Get;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Support\Exceptions\Halt;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString;
class CreateHostingSubscription extends Page
{
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.create-hosting-subscription';
protected static ?string $navigationGroup = 'Hosting Services';
protected static bool $shouldRegisterNavigation = false;
protected static ?string $slug = 'hosting-subscriptions/create';
protected static ?string $title = 'Create Hosting Account';
public $state = [];
public function verifyDomain($domain)
{
$verifyPHPContent = <<<EOT
<?php
if (isset(\$_GET['verified'])) {
echo 'Domain verified';
}
?>
EOT;
;
$file = fopen("/var/www/html/verify.php", "w") or die("Unable to open file!");
fwrite($file, $verifyPHPContent);
fclose($file);
$errors = [];
// Check if domain is pointing to the server
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "http://$domain/verify.php?verified=1");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
$result = curl_exec($curl);
curl_close($curl);
if ($result !== 'Domain verified') {
$errors[] = 'Domain not pointing to the server';
}
// Check if www. domain is pointing to the server
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "http://www.$domain/verify.php?verified=1");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
$result = curl_exec($curl);
curl_close($curl);
if ($result !== 'Domain verified') {
$errors[] = 'www. domain not pointing to the server';
}
return [
'errors' => $errors,
'domain' => $domain
];
}
public function form(Form $form): Form
{
return $form
->statePath('state')
->schema([
Wizard::make([
Wizard\Step::make('Validation')
->schema([
TextInput::make('domain')
->required()
->regex('/^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i')
->disabled(function ($record) {
if (isset($record->exists)) {
return $record->exists;
} else {
return false;
}
})
->suffixIcon('heroicon-m-globe-alt')
->columnSpanFull(),
])->afterValidation(function () {
$domain = $this->state['domain'];
// validate domain
if (!filter_var($domain, FILTER_VALIDATE_DOMAIN)) {
$this->addError('domain', 'Invalid domain name');
return;
}
// Verify domain if pointing to the server
$verify = $this->verifyDomain($domain);
if (isset($verify['errors']) && count($verify['errors']) > 0) {
$this->replaceMountedAction('firstVerifyDomain', ['domain' => $domain]);
throw new Halt();
}
}),
Wizard\Step::make('Customer Information')
->schema([
Select::make('customer_id')
->label('Customer')
->options(
\App\Models\Customer::all()->pluck('name', 'id')
)
->required()->columnSpanFull(),
]),
Wizard\Step::make('Building Hosting Account')
->schema([
Select::make('hosting_plan_id')
->label('Hosting Plan')
->options(
\App\Models\HostingPlan::all()->pluck('name', 'id')
)
->required()->columnSpanFull(),
Checkbox::make('advanced')
->live()
->columnSpanFull(),
TextInput::make('system_username')
->hidden(fn(Get $get): bool => !$get('advanced'))
->disabled(function ($record) {
if (isset($record->exists)) {
return $record->exists;
} else {
return false;
}
})
->suffixIcon('heroicon-m-user'),
TextInput::make('system_password')
->hidden(fn(Get $get): bool => !$get('advanced'))
->disabled(function ($record) {
if (isset($record->exists)) {
return $record->exists;
} else {
return false;
}
})
->suffixIcon('heroicon-m-lock-closed'),
]),
])
->submitAction(new HtmlString(Blade::render(<<<BLADE
<x-filament::button
wire:loading.attr="disabled"
wire:click="createHostingAccount"
>
Create Hosting Account
</x-filament::button>
BLADE)))
->columnSpanFull(),
]);
}
public function createHostingAccount()
{
$domain = $this->state['domain'];
$findDomain = Domain::where('domain', $domain)->first();
if ($findDomain) {
$this->replaceMountedAction('errorModal', ['message' => 'Domain already exists']);
return;
}
if (!empty($this->state['system_username'])) {
$findHostingSubscription = HostingSubscription::where('system_username', $this->state['system_username'])->first();
if ($findHostingSubscription) {
$this->replaceMountedAction('errorModal', ['message' => 'System username already exists']);
return;
}
}
$hostingSubscription = new HostingSubscription();
$hostingSubscription->customer_id = $this->state['customer_id'];
$hostingSubscription->hosting_plan_id = $this->state['hosting_plan_id'];
$hostingSubscription->domain = $domain;
if (isset($this->state['system_username'])) {
$hostingSubscription->system_username = $this->state['system_username'];
}
if (isset($this->state['system_password'])) {
$hostingSubscription->system_password = $this->state['system_password'];
}
$hostingSubscription->setup_date = Carbon::now();
$hostingSubscription->save();
ApacheBuild::dispatchSync();
return redirect(route('filament.admin.resources.hosting-subscriptions.index'));
}
public function errorModalAction(): Action
{
return Action::make('error')
->modalContent(view('filament.pages.create-hosting-subscription.error-modal', [
'domain' => $this->state['domain']
]))
->modalSubmitActionLabel('Ok');
}
public function firstVerifyDomainAction(): Action
{
// Get current server IP
$serverIp = shell_exec("hostname -I | cut -d' ' -f1");
$serverIp = trim($serverIp);
return Action::make('Verifying Domain')
->modalContent(view('filament.pages.create-hosting-subscription.verify-domain-modal', [
'domain' => $this->state['domain'],
'serverIp' =>$serverIp
]))
->modalSubmitActionLabel('Continue');
}
}

View file

@ -66,7 +66,6 @@ class Modules extends Page
if ($findModule) {
$findModule->delete();
}
shell_exec('phyre-php /usr/local/phyre/web/artisan module:disable ' . $module);
}
public function openInstallModal($module)
@ -101,8 +100,6 @@ class Modules extends Page
$this->installLogPulling = false;
shell_exec('phyre-php /usr/local/phyre/web/artisan module:enable ' . $module);
$moduleInfo = ModulesManager::getModuleInfo($module);
if (isset($moduleInfo['adminUrl'])) {
return $this->redirect($moduleInfo['adminUrl']);

View file

@ -22,11 +22,6 @@ class RepairTool extends Page
session()->flash('message', 'RunRepair command executed successfully.');
}
public function runRenewSSL()
{
Artisan::call('ssl-manager:renew-ssl');
session()->flash('message', 'RenewSSL command executed successfully.');
}
public function runDomainRepair()
{
Artisan::call('phyre:run-domain-repair');

View file

@ -331,7 +331,7 @@ class DomainResource extends Resource
->color('gray')
->url(fn ($record): string => 'http://'.$record->domain, true),
// Tables\Actions\EditAction::make(),
Tables\Actions\EditAction::make(),
])
->filters([
@ -362,8 +362,8 @@ class DomainResource extends Resource
{
return [
'index' => Pages\ListDomains::route('/'),
// 'create' => Pages\CreateDomain::route('/create'),
// 'edit' => Pages\EditDomain::route('/{record}/edit'),
'create' => Pages\CreateDomain::route('/create'),
'edit' => Pages\EditDomain::route('/{record}/edit'),
// 'view' => Pages\ViewDomain::route('/{record}'),
];
}

View file

@ -13,7 +13,7 @@ class ListDomains extends ListRecords
protected function getHeaderActions(): array
{
return [
// Actions\CreateAction::make(),
Actions\CreateAction::make(),
];
}
}

View file

@ -20,17 +20,16 @@ use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\HtmlString;
use Filament\Forms\Components\Wizard;
class HostingSubscriptionResource extends Resource
{
protected static ?string $model = HostingSubscription::class;
protected static ?string $navigationIcon = 'heroicon-o-server-stack';
protected static ?string $navigationIcon = 'heroicon-o-star';
protected static ?string $navigationGroup = 'Hosting Services';
protected static ?string $label = 'Hosting Accounts';
protected static ?string $label = 'Subscriptions';
protected static ?int $navigationSort = 2;
@ -41,7 +40,74 @@ class HostingSubscriptionResource extends Resource
return $form
->schema([
Section::make('Hosting Subscription Information')->schema([
// Forms\Components\Placeholder::make('Website Link')
// ->hidden(function ($record) {
// if (isset($record->exists)) {
// return false;
// } else {
// return true;
// }
// })
// ->content(fn($record) => new HtmlString('
// <a href="http://' . $record->domain . '" target="_blank" class="text-sm font-medium text-primary-600 dark:text-primary-400">
// http://' . $record->domain . '
// </a>')),
Forms\Components\TextInput::make('domain')
->required()
->regex('/^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$/i')
->disabled(function ($record) {
if (isset($record->exists)) {
return $record->exists;
} else {
return false;
}
})
->suffixIcon('heroicon-m-globe-alt')
->columnSpanFull(),
Forms\Components\Select::make('customer_id')
->label('Customer')
->options(
\App\Models\Customer::all()->pluck('name', 'id')
)
->required()->columnSpanFull(),
Forms\Components\Select::make('hosting_plan_id')
->label('Hosting Plan')
->options(
\App\Models\HostingPlan::all()->pluck('name', 'id')
)
->required()->columnSpanFull(),
Forms\Components\Checkbox::make('advanced')
->live()
->columnSpanFull(),
Forms\Components\TextInput::make('system_username')
->hidden(fn(Forms\Get $get): bool => !$get('advanced'))
->disabled(function ($record) {
if (isset($record->exists)) {
return $record->exists;
} else {
return false;
}
})
->suffixIcon('heroicon-m-user'),
Forms\Components\TextInput::make('system_password')
->hidden(fn(Forms\Get $get): bool => !$get('advanced'))
->disabled(function ($record) {
if (isset($record->exists)) {
return $record->exists;
} else {
return false;
}
})
->suffixIcon('heroicon-m-lock-closed'),
]),
]);
}
@ -110,13 +176,13 @@ class HostingSubscriptionResource extends Resource
->icon('heroicon-m-arrow-top-right-on-square')
->color('gray')
->url(fn($record): string => 'http://' . $record->domain, true),
// Tables\Actions\EditAction::make(),
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
// Tables\Actions\BulkActionGroup::make([
// Tables\Actions\DeleteBulkAction::make(),
// ]),
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
@ -139,7 +205,8 @@ class HostingSubscriptionResource extends Resource
{
return [
'index' => Pages\ListHostingSubscriptions::route('/'),
// 'edit' => Pages\EditHostingSubscription::route('/{record}/edit'),
'create' => Pages\CreateHostingSubscription::route('/create'),
'edit' => Pages\EditHostingSubscription::route('/{record}/edit'),
];
}

View file

@ -0,0 +1,11 @@
<?php
namespace App\Filament\Resources\HostingSubscriptionResource\Pages;
use App\Filament\Resources\HostingSubscriptionResource;
use Filament\Resources\Pages\CreateRecord;
class CreateHostingSubscription extends CreateRecord
{
protected static string $resource = HostingSubscriptionResource::class;
}

View file

@ -13,10 +13,7 @@ class ListHostingSubscriptions extends ListRecords
protected function getHeaderActions(): array
{
return [
Actions\Action::make('create')
->label('Create Hosting Account')
->icon('heroicon-o-plus')
->url(route('filament.admin.pages.hosting-subscriptions.create'))
Actions\CreateAction::make(),
];
}
}

View file

@ -4,7 +4,6 @@ namespace App\Models;
use App\Actions\ApacheWebsiteDelete;
use App\Events\DomainIsCreated;
use App\Events\DomainIsDeleted;
use App\Events\ModelDomainDeleting;
use App\Jobs\ApacheBuild;
use App\Models\Scopes\CustomerHostingSubscriptionScope;
@ -12,9 +11,7 @@ use App\ShellApi;
use App\VirtualHosts\DTO\ApacheVirtualHostSettings;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Modules\SSLManager\App\Jobs\SecureDomain;
// use Modules\Docker\App\Models\DockerContainer;
use Modules\Docker\App\Models\DockerContainer;
class Domain extends Model
{
@ -87,19 +84,7 @@ class Domain extends Model
$model->configureVirtualHost(true);
try {
$build = new ApacheBuild();
$build->handle();
} catch (\Exception $e) {
// $this->error($e->getMessage());
}
try {
$run = new SecureDomain($model->id);
$run->handle();
} catch (\Exception $e) {
// $this->error($e->getMessage());
}
ApacheBuild::dispatch();
});
@ -123,8 +108,6 @@ class Domain extends Model
ApacheBuild::dispatch();
event(new DomainIsDeleted($model));
});
}
@ -164,8 +147,6 @@ class Domain extends Model
}
}
$this->server_application_type = 'apache_php';
if ($this->is_installed_default_app_template == null) {
$this->is_installed_default_app_template = 1;
$this->saveQuietly();
@ -252,7 +233,6 @@ class Domain extends Model
$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'];
@ -345,17 +325,17 @@ class Domain extends Model
}
}
// 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);
// }
// }
// }
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);
}
}
}
}
$virtualHostSettings = $apacheVirtualHostBuilder->getSettings();

View file

@ -0,0 +1,437 @@
<?php
namespace App\Models;
use App\Actions\ApacheWebsiteDelete;
use App\Events\DomainIsCreated;
use App\Events\ModelDomainDeleting;
use App\ShellApi;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Modules\Docker\App\Models\DockerContainer;
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',
];
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);
});
}
});
}
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) {
if (empty($model->domain_public)) {
return;
}
$findHostingSubscription = HostingSubscription::where('id', $model->hosting_subscription_id)->first();
if (! $findHostingSubscription) {
return;
}
ShellApi::safeDelete($model->domain_root, ['/home/' . $findHostingSubscription->system_username]);
$whiteListedPathsForDelete = [
'/etc/apache2/sites-available',
'/etc/apache2/sites-enabled',
];
$apacheConf = '/etc/apache2/sites-available/'.$model->domain.'.conf';
ShellApi::safeDelete($apacheConf, $whiteListedPathsForDelete);
$apacheConfEnabled = '/etc/apache2/sites-enabled/'.$model->domain.'.conf';
ShellApi::safeDelete($apacheConfEnabled, $whiteListedPathsForDelete);
// SSL
$apacheSSLConf = '/etc/apache2/sites-available/'.$model->domain.'-ssl.conf';
ShellApi::safeDelete($apacheSSLConf, $whiteListedPathsForDelete);
$apacheSSLConfEnabled = '/etc/apache2/sites-enabled/'.$model->domain.'-ssl.conf';
ShellApi::safeDelete($apacheSSLConfEnabled, $whiteListedPathsForDelete);
});
}
public function hostingSubscription()
{
return $this->belongsTo(HostingSubscription::class);
}
public function configureVirtualHost($reloadApache = true)
{
$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');
}
if (empty($this->domain_root)) {
throw new \Exception('Domain root not found');
}
if (!is_dir($this->domain_root)) {
mkdir($this->domain_root, 0711, true);
}
if (!is_dir($this->domain_public)) {
mkdir($this->domain_public, 0755, true);
}
if (!is_dir($this->home_root)) {
mkdir($this->home_root, 0711, true);
}
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);
shell_exec('chmod -R 0711 '.$this->home_root);
shell_exec('chmod -R 0711 '.$this->domain_root);
shell_exec('chmod -R 775 '.$this->domain_public);
if (!is_dir($this->domain_root.'/logs/apache2')) {
shell_exec('mkdir -p '.$this->domain_root.'/logs/apache2');
}
shell_exec('chown -R '.$findHostingSubscription->system_username.':'.$webUserGroup.' '.$this->domain_root.'/logs/apache2');
shell_exec('chmod -R 775 '.$this->domain_root.'/logs/apache2');
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');
$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);
} else if ($this->status == self::STATUS_DEACTIVATED) {
$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);
} else {
$apacheVirtualHostBuilder->setEnableLogs(true);
$apacheVirtualHostBuilder->setAdditionalServices($findHostingPlan->additional_services);
$apacheVirtualHostBuilder->setAppType($appType);
$apacheVirtualHostBuilder->setAppVersion($appVersion);
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']);
}
}
if ($this->server_application_type == 'apache_python') {
$apacheVirtualHostBuilder->setAppType('python');
$apacheVirtualHostBuilder->setPassengerAppRoot($this->domain_public);
$apacheVirtualHostBuilder->setPassengerAppType('python');
if (isset($this->server_application_settings['python_version'])) {
$apacheVirtualHostBuilder->setAppVersion($this->server_application_settings['python_version']);
}
}
if ($this->server_application_type == 'apache_ruby') {
$apacheVirtualHostBuilder->setAppType('ruby');
$apacheVirtualHostBuilder->setPassengerAppRoot($this->domain_public);
$apacheVirtualHostBuilder->setPassengerAppType('ruby');
if (isset($this->server_application_settings['ruby_version'])) {
$apacheVirtualHostBuilder->setAppVersion($this->server_application_settings['ruby_version']);
}
}
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);
}
}
}
}
$apacheBaseConfig = $apacheVirtualHostBuilder->buildConfig();
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);
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');
}
}
}
// Reload apache
if ($reloadApache) {
shell_exec('systemctl reload apache2');
}
}
}

View file

@ -61,21 +61,12 @@ class ModulesManager
if ($findModule) {
$installed = 1;
}
// $iconUrl = route('module.icon.render', ['module' => $module]);
$iconRendered = '';
if (file_exists(base_path($logoIcon))) {
$iconRendered = file_get_contents(base_path($logoIcon));
}
return [
'name' => $module,
'description' => '',
'description' => 'A drag and drop website builder and a powerful next-generation CMS.',
'url' => $url,
'adminUrl' => $adminUrl,
// 'iconUrl' => $iconUrl,
'iconRendered'=>$iconRendered,
'iconUrl' => url('images/modules/' . $module . '.png'),
'logoIcon' => $logoIcon,
'category' => $category,
'installed'=>$installed,

View file

@ -35,6 +35,7 @@ class AdminPanelProvider extends PanelProvider
{
public function panel(Panel $panel): Panel
{
$panel->default()
->darkMode(true)
->id('admin')
@ -48,15 +49,13 @@ class AdminPanelProvider extends PanelProvider
->unsavedChangesAlerts()
->globalSearch(true)
->databaseNotifications()
->font('Exo 2')
->font('Albert Sans')
->sidebarWidth('15rem')
// ->brandLogo(fn () => view('filament.admin.logo'))
->navigationGroups([
'Hosting Services' => NavigationGroup::make()->label('Hosting Services'),
// 'Docker' => NavigationGroup::make()->label('Docker'),
'SSL Manager'=> NavigationGroup::make()->label('SSL Manager')
// ->icon('ssl_manager-logo')
,
'SSL Manager'=> NavigationGroup::make()->label('SSL Manager')->icon('ssl_manager-logo'),
'Server Management' => NavigationGroup::make()->label('Server Management'),
])
->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
@ -99,7 +98,7 @@ class AdminPanelProvider extends PanelProvider
$defaultColor = Color::Yellow;
$brandLogo = null;
$brandName = null;
$isAppInstalled = file_exists(storage_path('installed'));
$isAppInstalled = file_exists(storage_path('installed'));
if ($isAppInstalled && !(php_sapi_name() === 'cli' || php_sapi_name() === 'phpdbg')) {
if (setting('general.brand_logo_url')) {
$brandLogo = setting('general.brand_logo_url');
@ -153,7 +152,7 @@ class AdminPanelProvider extends PanelProvider
} else {
$panel->brandLogo(asset('images/phyre-logo.svg'));
}
$panel->brandLogoHeight('2.2rem')
->colors([
'primary'=>$defaultColor,

View file

@ -18,8 +18,8 @@
"guzzlehttp/guzzle": "^7.2",
"jaocero/radio-deck": "^1.2",
"jelix/inifile": "^3.4",
"laravel/framework": "^11.0",
"laravel/sanctum": "^4.0",
"laravel/framework": "^10.10",
"laravel/sanctum": "^3.3",
"laravel/tinker": "^2.8",
"leandrocfe/filament-apex-charts": "^3.1",
"mkocansey/bladewind": "^2.4",
@ -32,7 +32,7 @@
"riodwanto/filament-ace-editor": "^1.0",
"spatie/ssh": "^1.10",
"stechstudio/filament-impersonate": "^3.8",
"symfony/process": "^7.2",
"symfony/process": "^6.3",
"symfony/yaml": "^7.0",
"torann/geoip": "^3.0",
"wikimedia/composer-merge-plugin": "^2.1",
@ -44,7 +44,7 @@
"laravel/pint": "^1.15",
"laravel/sail": "^1.18",
"mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^8.5",
"nunomaduro/collision": "^7.0",
"phpunit/phpunit": "^10.1",
"spatie/laravel-ignition": "^2.0"
},

1423
web/composer.lock generated

File diff suppressed because it is too large Load diff

265
web/package-lock.json generated
View file

@ -13,14 +13,14 @@
"@xterm/xterm": "^5.5.0"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.10",
"@tailwindcss/typography": "^0.5.16",
"autoprefixer": "^10.4.20",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.12",
"autoprefixer": "^10.4.19",
"axios": "^1.6.1",
"laravel-vite-plugin": "^0.8.0",
"postcss": "^8.5.2",
"postcss": "^8.4.38",
"postcss-nesting": "^12.1.1",
"tailwindcss": "^3.4.17",
"tailwindcss": "^3.4.3",
"tippy.js": "^6.3.7",
"vite": "^4.0.0"
}
@ -510,24 +510,22 @@
}
},
"node_modules/@tailwindcss/forms": {
"version": "0.5.10",
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.10.tgz",
"integrity": "sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw==",
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.7.tgz",
"integrity": "sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==",
"dev": true,
"license": "MIT",
"dependencies": {
"mini-svg-data-uri": "^1.2.3"
},
"peerDependencies": {
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1"
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1"
}
},
"node_modules/@tailwindcss/typography": {
"version": "0.5.16",
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz",
"integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==",
"version": "0.5.12",
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.12.tgz",
"integrity": "sha512-CNwpBpconcP7ppxmuq3qvaCxiRWnbhANpY/ruH4L5qs2GCiVDJXde/pjj2HWPV1+Q4G9+V/etrwUYopdcjAlyg==",
"dev": true,
"license": "MIT",
"dependencies": {
"lodash.castarray": "^4.4.0",
"lodash.isplainobject": "^4.0.6",
@ -535,7 +533,7 @@
"postcss-selector-parser": "6.0.10"
},
"peerDependencies": {
"tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1"
"tailwindcss": ">=3.0.0 || insiders"
}
},
"node_modules/@xterm/addon-canvas": {
@ -639,9 +637,9 @@
"dev": true
},
"node_modules/autoprefixer": {
"version": "10.4.20",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
"integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==",
"version": "10.4.19",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz",
"integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==",
"dev": true,
"funding": [
{
@ -657,13 +655,12 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"browserslist": "^4.23.3",
"caniuse-lite": "^1.0.30001646",
"browserslist": "^4.23.0",
"caniuse-lite": "^1.0.30001599",
"fraction.js": "^4.3.7",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.1",
"picocolors": "^1.0.0",
"postcss-value-parser": "^4.2.0"
},
"bin": {
@ -715,22 +712,21 @@
}
},
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dev": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
"fill-range": "^7.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/browserslist": {
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
"integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz",
"integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==",
"dev": true,
"funding": [
{
@ -746,12 +742,11 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"caniuse-lite": "^1.0.30001688",
"electron-to-chromium": "^1.5.73",
"node-releases": "^2.0.19",
"update-browserslist-db": "^1.1.1"
"caniuse-lite": "^1.0.30001587",
"electron-to-chromium": "^1.4.668",
"node-releases": "^2.0.14",
"update-browserslist-db": "^1.0.13"
},
"bin": {
"browserslist": "cli.js"
@ -770,9 +765,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001700",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz",
"integrity": "sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==",
"version": "1.0.30001605",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001605.tgz",
"integrity": "sha512-nXwGlFWo34uliI9z3n6Qc0wZaf7zaZWA1CPZ169La5mV3I/gem7bst0vr5XQH5TJXZIMfDeZyOrZnSlVzKxxHQ==",
"dev": true,
"funding": [
{
@ -787,8 +782,7 @@
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "CC-BY-4.0"
]
},
"node_modules/chokidar": {
"version": "3.6.0",
@ -919,11 +913,10 @@
"dev": true
},
"node_modules/electron-to-chromium": {
"version": "1.5.102",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.102.tgz",
"integrity": "sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q==",
"dev": true,
"license": "ISC"
"version": "1.4.724",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.724.tgz",
"integrity": "sha512-RTRvkmRkGhNBPPpdrgtDKvmOEYTrPlXDfc0J/Nfq5s29tEahAwhiX4mmhNzj6febWMleulxVYPh7QwCSL/EldA==",
"dev": true
},
"node_modules/emoji-regex": {
"version": "9.2.2",
@ -969,11 +962,10 @@
}
},
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
"integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
@ -1016,11 +1008,10 @@
}
},
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
},
@ -1219,7 +1210,6 @@
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.12.0"
}
@ -1249,11 +1239,10 @@
}
},
"node_modules/jiti": {
"version": "1.21.7",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
"version": "1.21.0",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
"integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
"dev": true,
"license": "MIT",
"bin": {
"jiti": "bin/jiti.js"
}
@ -1275,16 +1264,12 @@
}
},
"node_modules/lilconfig": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
"integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
"integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antonk52"
"node": ">=10"
}
},
"node_modules/lines-and-columns": {
@ -1330,13 +1315,12 @@
}
},
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
"dev": true,
"license": "MIT",
"dependencies": {
"braces": "^3.0.3",
"braces": "^3.0.2",
"picomatch": "^2.3.1"
},
"engines": {
@ -1409,9 +1393,9 @@
}
},
"node_modules/nanoid": {
"version": "3.3.8",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
"integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"dev": true,
"funding": [
{
@ -1419,7 +1403,6 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@ -1428,11 +1411,10 @@
}
},
"node_modules/node-releases": {
"version": "2.0.19",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
"integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
"dev": true,
"license": "MIT"
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
"dev": true
},
"node_modules/normalize-path": {
"version": "3.0.0",
@ -1502,11 +1484,10 @@
}
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC"
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
"dev": true
},
"node_modules/picomatch": {
"version": "2.3.1",
@ -1539,9 +1520,9 @@
}
},
"node_modules/postcss": {
"version": "8.5.2",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz",
"integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==",
"version": "8.4.38",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
"integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
"dev": true,
"funding": [
{
@ -1557,11 +1538,10 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.8",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
"nanoid": "^3.3.7",
"picocolors": "^1.0.0",
"source-map-js": "^1.2.0"
},
"engines": {
"node": "^10 || ^12 || >=14"
@ -1638,38 +1618,42 @@
}
}
},
"node_modules/postcss-nested": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
"integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
"node_modules/postcss-load-config/node_modules/lilconfig": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz",
"integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==",
"dev": true,
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antonk52"
}
},
"node_modules/postcss-nested": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
"integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"postcss-selector-parser": "^6.1.1"
"postcss-selector-parser": "^6.0.11"
},
"engines": {
"node": ">=12.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
"peerDependencies": {
"postcss": "^8.2.14"
}
},
"node_modules/postcss-nested/node_modules/postcss-selector-parser": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
"version": "6.0.16",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz",
"integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==",
"dev": true,
"license": "MIT",
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@ -1928,11 +1912,10 @@
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
"integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
@ -2068,34 +2051,33 @@
}
},
"node_modules/tailwindcss": {
"version": "3.4.17",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz",
"integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==",
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz",
"integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
"arg": "^5.0.2",
"chokidar": "^3.6.0",
"chokidar": "^3.5.3",
"didyoumean": "^1.2.2",
"dlv": "^1.1.3",
"fast-glob": "^3.3.2",
"fast-glob": "^3.3.0",
"glob-parent": "^6.0.2",
"is-glob": "^4.0.3",
"jiti": "^1.21.6",
"lilconfig": "^3.1.3",
"micromatch": "^4.0.8",
"jiti": "^1.21.0",
"lilconfig": "^2.1.0",
"micromatch": "^4.0.5",
"normalize-path": "^3.0.0",
"object-hash": "^3.0.0",
"picocolors": "^1.1.1",
"postcss": "^8.4.47",
"picocolors": "^1.0.0",
"postcss": "^8.4.23",
"postcss-import": "^15.1.0",
"postcss-js": "^4.0.1",
"postcss-load-config": "^4.0.2",
"postcss-nested": "^6.2.0",
"postcss-selector-parser": "^6.1.2",
"resolve": "^1.22.8",
"sucrase": "^3.35.0"
"postcss-load-config": "^4.0.1",
"postcss-nested": "^6.0.1",
"postcss-selector-parser": "^6.0.11",
"resolve": "^1.22.2",
"sucrase": "^3.32.0"
},
"bin": {
"tailwind": "lib/cli.js",
@ -2106,11 +2088,10 @@
}
},
"node_modules/tailwindcss/node_modules/postcss-selector-parser": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
"version": "6.0.16",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz",
"integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==",
"dev": true,
"license": "MIT",
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@ -2154,7 +2135,6 @@
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
@ -2169,9 +2149,9 @@
"dev": true
},
"node_modules/update-browserslist-db": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz",
"integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==",
"version": "1.0.13",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
"integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
"dev": true,
"funding": [
{
@ -2187,10 +2167,9 @@
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"dependencies": {
"escalade": "^3.2.0",
"picocolors": "^1.1.1"
"escalade": "^3.1.1",
"picocolors": "^1.0.0"
},
"bin": {
"update-browserslist-db": "cli.js"

View file

@ -6,14 +6,14 @@
"build": "vite build"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.10",
"@tailwindcss/typography": "^0.5.16",
"autoprefixer": "^10.4.20",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.12",
"autoprefixer": "^10.4.19",
"axios": "^1.6.1",
"laravel-vite-plugin": "^0.8.0",
"postcss": "^8.5.2",
"postcss": "^8.4.38",
"postcss-nesting": "^12.1.1",
"tailwindcss": "^3.4.17",
"tailwindcss": "^3.4.3",
"tippy.js": "^6.3.7",
"vite": "^4.0.0"
},

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
{
"resources/css/app.css": {
"file": "assets/app-0fd9001c.css",
"file": "assets/app-4e206fd3.css",
"isEntry": true,
"src": "resources/css/app.css"
},

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
function i({state:a,splitKeys:n}){return{newTag:"",state:a,createTag:function(){if(this.newTag=this.newTag.trim(),this.newTag!==""){if(this.state.includes(this.newTag)){this.newTag="";return}this.state.push(this.newTag),this.newTag=""}},deleteTag:function(t){this.state=this.state.filter(e=>e!==t)},reorderTags:function(t){let e=this.state.splice(t.oldIndex,1)[0];this.state.splice(t.newIndex,0,e),this.state=[...this.state]},input:{"x-on:blur":"createTag()","x-model":"newTag","x-on:keydown"(t){["Enter",...n].includes(t.key)&&(t.preventDefault(),t.stopPropagation(),this.createTag())},"x-on:paste"(){this.$nextTick(()=>{if(n.length===0){this.createTag();return}let t=n.map(e=>e.replace(/[/\-\\^$*+?.()|[\]{}]/g,"\\$&")).join("|");this.newTag.split(new RegExp(t,"g")).forEach(e=>{this.newTag=e,this.createTag()})})}}}}export{i as default};
function i({state:a,splitKeys:n}){return{newTag:"",state:a,createTag:function(){if(this.newTag=this.newTag.trim(),this.newTag!==""){if(this.state.includes(this.newTag)){this.newTag="";return}this.state.push(this.newTag),this.newTag=""}},deleteTag:function(t){this.state=this.state.filter(e=>e!==t)},reorderTags:function(t){let e=this.state.splice(t.oldIndex,1)[0];this.state.splice(t.newIndex,0,e),this.state=[...this.state]},input:{["x-on:blur"]:"createTag()",["x-model"]:"newTag",["x-on:keydown"](t){["Enter",...n].includes(t.key)&&(t.preventDefault(),t.stopPropagation(),this.createTag())},["x-on:paste"](){this.$nextTick(()=>{if(n.length===0){this.createTag();return}let t=n.map(e=>e.replace(/[/\-\\^$*+?.()|[\]{}]/g,"\\$&")).join("|");this.newTag.split(new RegExp(t,"g")).forEach(e=>{this.newTag=e,this.createTag()})})}}}}export{i as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
function m({state:r,statePath:s,placeholder:o,aceUrl:a,extensions:n,config:h={},options:c={},darkTheme:l,disableDarkTheme:d}){return{state:r,statePath:s,placeholder:o,options:c,darkTheme:l,disableDarkTheme:d,editor:null,observer:null,async init(){if(!await this.importAceEditor(a)){console.error("Failed to load the ACE editor core.");return}await this.importExtensions(n)||console.error("Failed to load ACE editor extensions."),this.configureAce(h),this.initializeEditor(),this.applyInitialTheme(),this.observeDarkModeChanges()},async importAceEditor(t){try{return await import(t),!0}catch(e){return console.error("Error importing the ACE editor core:",e),!1}},async importExtensions(t){try{let e=Object.values(t).map(i=>import(i));return await Promise.all(e),!0}catch(e){return console.error("Error importing ACE editor extensions:",e),!1}},configureAce(t){Object.entries(t).forEach(([e,i])=>ace.config.set(e,i))},initializeEditor(){this.editor=ace.edit(this.$refs.aceCodeEditor),this.editor.setOptions(this.options),this.editor.session.setValue(this.state?this.state:this.placeholder),this.editor.session.on("change",()=>{this.state=this.editor.getValue()})},applyInitialTheme(){this.disableDarkTheme?this.editor.setTheme(this.options.theme):this.setTheme()},observeDarkModeChanges(){if(this.disableDarkTheme)return;let t=document.querySelector("html");this.observer=new MutationObserver(()=>this.setTheme()),this.observer.observe(t,{attributes:!0,attributeFilter:["class"]})},setTheme(){let e=document.querySelector("html").classList.contains("dark")?this.darkTheme:this.options.theme;this.editor&&this.editor.setTheme(e)}}}export{m as default};
function m({state:r,statePath:o,placeholder:s,aceUrl:a,extensions:n,config:h={},options:c={},darkTheme:l,disableDarkTheme:d}){return{state:r,statePath:o,placeholder:s,options:c,darkTheme:l,disableDarkTheme:d,editor:null,observer:null,async init(){if(!await this.importAceEditor(a)){console.error("Failed to load the ACE editor core.");return}await this.importExtensions(n)||console.error("Failed to load ACE editor extensions."),this.configureAce(h),this.initializeEditor(),this.applyInitialTheme(),this.observeDarkModeChanges()},async importAceEditor(t){try{return await import(t),!0}catch(e){return console.error("Error importing the ACE editor core:",e),!1}},async importExtensions(t){try{let e=Object.values(t).map(i=>import(i));return await Promise.all(e),!0}catch(e){return console.error("Error importing ACE editor extensions:",e),!1}},configureAce(t){Object.entries(t).forEach(([e,i])=>ace.config.set(e,i))},initializeEditor(){this.editor=ace.edit(this.$refs.aceCodeEditor),this.editor.setOptions(this.options),this.editor.setValue(this.state?this.state:this.placeholder),this.editor.session.on("change",()=>{this.state=this.editor.getValue()})},applyInitialTheme(){this.disableDarkTheme?this.editor.setTheme(this.options.theme):this.setTheme()},observeDarkModeChanges(){if(this.disableDarkTheme)return;let t=document.querySelector("html");this.observer=new MutationObserver(()=>this.setTheme()),this.observer.observe(t,{attributes:!0,attributeFilter:["class"]})},setTheme(){let e=document.querySelector("html").classList.contains("dark")?this.darkTheme:this.options.theme;this.editor&&this.editor.setTheme(e)}}}export{m as default};

View file

@ -1,69 +1,7 @@
@import '/vendor/filament/filament/resources/css/theme.css';
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
font-family: var(--font-family) !important;
}
.fi-sidebar-item .fi-sidebar-item-button {
@apply rounded-lg;
}
.fi-sidebar-item-active .fi-sidebar-item-button {
@apply rounded-lg ; /* bg-[#e5e9f0] */
}
.fi-input-wrp {
@apply ring-1 ;
}
.fi-ta-ctn {
@apply shadow-md rounded-2xl border-none ring-0 dark:ring-1; /*rounded-none*/
}
.fi-section, .fi-wi-stats-overview-stat {
@apply shadow-md rounded-2xl border-none ring-0 dark:ring-1;
}
.fi-topbar .fi-tenant-menu {
@apply lg:!hidden;
}
.fi-tenant-menu {
@apply rounded-lg mt-4;
}
.fi-global-search-field .fi-input-wrp, .fi-ta-search-field .fi-input-wrp {
@apply rounded-full;
}
.fi-global-search-field .fi-input-wrp {
@apply ring-4;
}
.fi-global-search-field .fi-input-wrp .fi-input-wrp-prefix {
@apply rounded-full ps-2 mr-2;
}
.fi-btn:not(.fi-btn-group .fi-btn) {
@apply rounded-full;
}
.fi-btn-group > .fi-btn:first-of-type {
@apply rounded-s-full;
}
.fi-btn-group > .fi-btn:last-of-type {
@apply rounded-e-full;
}
.fi-btn-group {
@apply rounded-full;
}
.fi-badge {
@apply rounded-xl;
}
/*.fi-sidebar {
background-color: rgba(255, 255, 255, 0.07) !important;
}*/

View file

@ -1,15 +0,0 @@
.fi-simple-layout {
> .fi-simple-main-ctn {
@apply bg-[#4880FF] dark:bg-[var(--ds-dark-bg-primary-color)];
@apply bg-[url(/vendor/nuxtifyts/dash-stack-theme/dash-stack-shape.svg)];
@apply bg-no-repeat bg-cover;
> .fi-simple-main {
@apply bg-white dark:bg-[var(--ds-dark-bg-secondary-color)] rounded-3xl;
.fi-simple-header-heading {
@apply text-2xl;
}
}
}
}

View file

@ -1,7 +0,0 @@
<x-filament-panels::page>
<div>
{{$this->form}}
</div>
</x-filament-panels::page>

View file

@ -1,15 +0,0 @@
<div>
@php
$args = $this->error->getArguments();
@endphp
@if(isset($args['message']))
<h4 class="text-red-500">
{{ $args['message'] }}
</h4>
@endif
</div>

View file

@ -1,50 +0,0 @@
<div>
<h2 class="text-2xl font-semibold text-gray-900 mb-4">
Your domain must be verified before you can proceed.
</h2>
<p class="mb-4">To link your domain to our server, follow these steps:</p>
<ol class="list-decimal pl-6 mb-4">
<li>Log in to your domain registrar's <strong>DNS Management Panel</strong>.</li>
<li>Locate the option to manage <strong>DNS Records</strong> or <strong>Zone Editor</strong>.</li>
<li>Add a new <strong>A Record</strong> with the following details:</li>
</ol>
<div class="overflow-x-auto bg-white dark:bg-white/5 shadow-md rounded-lg">
<table class="min-w-full text-left table-auto">
<thead>
<tr class="bg-primary-500 dark:bg-white/5 text-white">
<th class="py-2 px-4">Record Type</th>
<th class="py-2 px-4">Host/Name</th>
<th class="py-2 px-4">Value (IP Address)</th>
<th class="py-2 px-4">TTL</th>
</tr>
</thead>
<tbody>
<tr class="border-b">
<td class="py-2 px-4">A</td>
<td class="py-2 px-4">@ (or {{$domain}})</td>
<td class="py-2 px-4"><strong>{{$serverIp}}</strong></td>
<td class="py-2 px-4">300 (or default)</td>
</tr>
<tr class="border-b">
<td class="py-2 px-4">A</td>
<td class="py-2 px-4">www</td>
<td class="py-2 px-4"><strong>{{$serverIp}}</strong></td>
<td class="py-2 px-4">300 (or default)</td>
</tr>
</tbody>
</table>
</div>
<p class="mt-4"><strong>4.</strong> Save the changes and wait for DNS propagation (may take a few minutes to several hours).</p>
<p class="mt-2"><strong>5.</strong> Verify by checking your domain with this command:</p>
<pre class="bg-gray-200 dark:bg-white/5 p-2 rounded-md my-2"><code>nslookup {{$domain}}</code></pre>
<p>or</p>
<pre class="bg-gray-200 dark:bg-white/5 p-2 rounded-md my-2"><code>dig A {{$domain}} +short</code></pre>
<p class="mt-4"><strong>🔹 Note:</strong> If you want to set up a subdomain (e.g., <code>app.{{$domain}}</code>), use <code>app</code> in the <strong>Host/Name</strong> field instead of <code>@</code>.</p>
</div>

View file

@ -41,10 +41,8 @@
<div class="sm:flex gap-3 px-6 py-6 rounded-xl bg-white shadow-sm ring-1 ring-gray-950/5 dark:bg-gray-900 dark:ring-white/10">
<div class="">
<div class="flex flex-col items-center w-16">
{!! $module['iconRendered'] !!}
<x-filament::icon :icon="$module['logoIcon']"
class="w-12 h-12 text-primary-500"/>
</div>
</div>
<div class="flex justify-between items-center w-full">

View file

@ -1,59 +1,56 @@
<x-filament-panels::page>
<style>
.repair-tool-wrapper {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-gap: 10px;
}
.repair-tool-action {
width: 100%;
cursor: pointer;
padding: 20px;
border: 1px solid #ccc;
border-radius: 4px;
background: #fff;
margin: 10px;
text-transform: uppercase;
font-weight: bold;
font-size: 12px;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
gap: 20px;
}
.repair-tool-action:hover {
background: #f9f9f9;
box-shadow: 0px 0px 3px #ccc;
}
</style>
<div>
@if (session()->has('message'))
<div class="p-4 mb-4 text-sm rounded-lg bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200">
<div class="alert alert-success">
{{ session('message') }}
</div>
@endif
<div class="repair-tool-wrapper max-w[15rem] flex flex-col gap-4 p-6 bg-white dark:bg-gray-800 rounded-lg shadow-md">
<!-- Repair Tool Action 1 -->
<div wire:click="runRepair" class="repair-tool-action flex items-center space-x-3 p-4 border-2 border-primary-500 dark:border-primary-700 rounded-lg cursor-pointer transition-all hover:border-primary-600 dark:hover:border-primary-800 dark:text-white disabled:opacity-50 disabled:cursor-not-allowed" wire:loading.attr="disabled">
<svg xmlns="http://www.w3.org/2000/svg" width="50%" viewBox="0 0 512 512" class="h-8 w-8">
<path fill="currentColor" d="m241.406 21l-15.22 34.75a182 182 0 0 0-23.467 2.97l-23.282-30.064l-25.094 8.532l-.125 38.25c-10.63 5.464-20.817 12.07-30.44 19.78L88.313 79.25L70.156 98.563L88.312 133a180.6 180.6 0 0 0-15.218 26.094l-38.938 1.062l-7.906 25.28l31.438 23.158c-1.505 9.38-2.24 18.858-2.282 28.344L20.5 254.625l3.656 26.25l38.313 7.5a182 182 0 0 0 8.5 23.5L45.72 343.22l14.093 22.436l39.25-9.187a185 185 0 0 0 7.718 8.53a187 187 0 0 0 17.72 16.125l-7.625 39.313l22.938 13.25l29.968-26.094a179.4 179.4 0 0 0 26.407 8.312l9.782 38.406l26.405 2.157l15.875-36.22c10.97-.66 21.904-2.3 32.656-4.938l25.22 29.22l24.593-9.844l-.72-14.813l-57.406-43.53c-16.712 4.225-34.042 5.356-51.063 3.436c-31.754-3.58-62.27-17.92-86.218-42.686c-54.738-56.614-53.173-146.67 3.438-201.406c27.42-26.513 62.69-39.963 98-40.344c37.59-.406 75.214 13.996 103.438 43.187c45.935 47.512 52.196 118.985 19.562 173.095l31.97 24.25a181 181 0 0 0 10.75-19.375l38.655-1.063l7.906-25.28l-31.217-23a183 183 0 0 0 2.28-28.594l34.688-17.625l-3.655-26.25l-38.28-7.5a182 182 0 0 0-12.75-32.125l22.81-31.594l-15.25-21.657l-37.56 10.906c-.472-.5-.93-1.007-1.408-1.5a185 185 0 0 0-18.937-17.064l7.188-37.125L334 43.78l-28.5 24.814c-9.226-3.713-18.702-6.603-28.313-8.75l-9.343-36.688zM183.25 174.5c-10.344.118-20.597 2.658-30 7.28l45.22 34.314c13.676 10.376 17.555 30.095 7.06 43.937c-10.498 13.85-30.656 15.932-44.53 5.408l-45.188-34.282c-4.627 24.793 4.135 51.063 25.594 67.344c19.245 14.597 43.944 17.33 65.22 9.688l4.78-1.72l4.03 3.063l135.19 102.564l4.03 3.062l-.344 5.063c-1.637 22.55 7.59 45.61 26.844 60.217c21.46 16.28 49.145 17.63 71.78 6.5l-45.186-34.28c-13.874-10.526-17.282-30.506-6.78-44.344c10.5-13.84 30.537-15.405 44.217-5.032l45.188 34.283c4.616-24.784-4.11-51.067-25.563-67.344c-19.313-14.658-43.817-17.562-64.968-10.033l-4.75 1.688l-4.03-3.063l-135.19-102.562l-4.03-3.063l.344-5.03c1.55-22.387-7.85-45.194-27.157-59.845c-12.544-9.516-27.222-13.978-41.78-13.812zm43.563 90.25l163.875 124.344L379.406 404L215.5 279.625z"/>
</svg>
<div>
Run Repair
</div>
<!-- Loading Spinner -->
<div wire:loading wire:target="runRepair" class="ml-2 spinner-border animate-spin h-5 w-5 border-t-2 dark:border-white border-primary-700 rounded-full"></div>
<div class="repair-tool-wrapper">
<div wire:click="runRepair" class="repair-tool-action">
<svg xmlns="http://www.w3.org/2000/svg" width="50%" viewBox="0 0 512 512"><path fill="currentColor" d="m241.406 21l-15.22 34.75a182 182 0 0 0-23.467 2.97l-23.282-30.064l-25.094 8.532l-.125 38.25c-10.63 5.464-20.817 12.07-30.44 19.78L88.313 79.25L70.156 98.563L88.312 133a180.6 180.6 0 0 0-15.218 26.094l-38.938 1.062l-7.906 25.28l31.438 23.158c-1.505 9.38-2.24 18.858-2.282 28.344L20.5 254.625l3.656 26.25l38.313 7.5a182 182 0 0 0 8.5 23.5L45.72 343.22l14.093 22.436l39.25-9.187a185 185 0 0 0 7.718 8.53a187 187 0 0 0 17.72 16.125l-7.625 39.313l22.938 13.25l29.968-26.094a179.4 179.4 0 0 0 26.407 8.312l9.782 38.406l26.405 2.157l15.875-36.22c10.97-.66 21.904-2.3 32.656-4.938l25.22 29.22l24.593-9.844l-.72-14.813l-57.406-43.53c-16.712 4.225-34.042 5.356-51.063 3.436c-31.754-3.58-62.27-17.92-86.218-42.686c-54.738-56.614-53.173-146.67 3.438-201.406c27.42-26.513 62.69-39.963 98-40.344c37.59-.406 75.214 13.996 103.438 43.187c45.935 47.512 52.196 118.985 19.562 173.095l31.97 24.25a181 181 0 0 0 10.75-19.375l38.655-1.063l7.906-25.28l-31.217-23a183 183 0 0 0 2.28-28.594l34.688-17.625l-3.655-26.25l-38.28-7.5a182 182 0 0 0-12.75-32.125l22.81-31.594l-15.25-21.657l-37.56 10.906c-.472-.5-.93-1.007-1.408-1.5a185 185 0 0 0-18.937-17.064l7.188-37.125L334 43.78l-28.5 24.814c-9.226-3.713-18.702-6.603-28.313-8.75l-9.343-36.688zM183.25 174.5c-10.344.118-20.597 2.658-30 7.28l45.22 34.314c13.676 10.376 17.555 30.095 7.06 43.937c-10.498 13.85-30.656 15.932-44.53 5.408l-45.188-34.282c-4.627 24.793 4.135 51.063 25.594 67.344c19.245 14.597 43.944 17.33 65.22 9.688l4.78-1.72l4.03 3.063l135.19 102.564l4.03 3.062l-.344 5.063c-1.637 22.55 7.59 45.61 26.844 60.217c21.46 16.28 49.145 17.63 71.78 6.5l-45.186-34.28c-13.874-10.526-17.282-30.506-6.78-44.344c10.5-13.84 30.537-15.405 44.217-5.032l45.188 34.283c4.616-24.784-4.11-51.067-25.563-67.344c-19.313-14.658-43.817-17.562-64.968-10.033l-4.75 1.688l-4.03-3.063l-135.19-102.562l-4.03-3.063l.344-5.03c1.55-22.387-7.85-45.194-27.157-59.845c-12.544-9.516-27.222-13.978-41.78-13.812zm43.563 90.25l163.875 124.344L379.406 404L215.5 279.625z"/></svg>
<div>
Run Repair
</div>
<!-- Repair Tool Action 2 -->
<div wire:click="runDomainRepair" class="repair-tool-action flex items-center space-x-3 p-4 border-2 border-primary-500 dark:border-primary-700 rounded-lg cursor-pointer transition-all hover:border-primary-600 dark:hover:border-primary-800 dark:text-white disabled:opacity-50 disabled:cursor-not-allowed" wire:loading.attr="disabled">
<svg xmlns="http://www.w3.org/2000/svg" width="50%" viewBox="0 0 24 24" class="h-8 w-8">
<path fill="currentColor" d="M2 14a1 1 0 1 1-2 0a1 1 0 0 1 2 0" opacity="0.5"/>
<path fill="currentColor" d="M6.719 10.262a1.73 1.73 0 0 0-2.458 0a1.757 1.757 0 0 0 0 2.476a1.73 1.73 0 0 0 2.458 0a.75.75 0 0 1 1.062 1.059a3.23 3.23 0 0 1-4.583 0a3.257 3.257 0 0 1 0-4.594a3.23 3.23 0 0 1 4.583 0a.75.75 0 0 1-1.062 1.059M8.5 11.5a3.25 3.25 0 1 1 6.5 0a3.25 3.25 0 0 1-6.5 0m3.25-1.75a1.75 1.75 0 1 0 0 3.5a1.75 1.75 0 0 0 0-3.5M18 8.25c-1.395 0-2.5 1.15-2.5 2.536V14a.75.75 0 0 0 1.5 0v-3.214c0-.587.462-1.036 1-1.036s1 .45 1 1.036V14a.75.75 0 0 0 1.5 0v-3.214c0-.587.462-1.036 1-1.036s1 .45 1 1.036V14a.75.75 0 0 0 1.5 0v-3.214C24 9.4 22.895 8.25 21.5 8.25c-.686 0-1.301.278-1.75.725A2.47 2.47 0 0 0 18 8.25"/>
</svg>
<div>
Run Domain Repair
</div>
<!-- Loading Spinner -->
<div wire:loading wire:target="runDomainRepair" class="ml-2 spinner-border animate-spin h-5 w-5 border-t-2 dark:border-white border-primary-700 rounded-full"></div>
</div>
<!-- Repair Tool Action 3 -->
<div wire:click="runRenewSSL" class="repair-tool-action flex items-center space-x-3 p-4 border-2 border-primary-500 dark:border-primary-700 rounded-lg cursor-pointer transition-all hover:border-primary-600 dark:hover:border-primary-800 dark:text-white disabled:opacity-50 disabled:cursor-not-allowed" wire:loading.attr="disabled">
<svg class="h-8 w-8" fill="currentColor" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
<title>letsencrypt</title>
<path d="M15.986 21.652c0.004-0 0.009-0 0.014-0 0.883 0 1.599 0.716 1.599 1.599 0 0.594-0.323 1.112-0.804 1.387l-0.008 0.004v1.556c-0.003 0.432-0.354 0.781-0.787 0.781s-0.784-0.349-0.787-0.781v-1.556c-0.488-0.28-0.812-0.798-0.812-1.391 0-0.878 0.708-1.591 1.584-1.598h0.001zM2.915 13.187c-0.573 0.044-1.021 0.52-1.021 1.1s0.448 1.056 1.017 1.1l0.004 0h3.747c0.573-0.044 1.021-0.52 1.021-1.1s-0.448-1.056-1.017-1.1l-0.004-0zM25.214 13.184c-0.608 0.002-1.1 0.495-1.1 1.103 0 0.609 0.494 1.103 1.103 1.103 0.030 0 0.059-0.001 0.088-0.003l-0.004 0h3.782c0.573-0.044 1.021-0.52 1.021-1.1s-0.448-1.056-1.017-1.1l-0.004-0h-3.782q-0.044-0.003-0.088-0.003zM15.991 12.555c0.003 0 0.006 0 0.009 0 1.485 0 2.689 1.204 2.689 2.689 0 0 0 0 0 0v0 1.859h-5.379v-1.859c0 0 0-0 0-0 0-1.482 1.199-2.684 2.68-2.689h0.001zM15.975 8.939c-3.472 0.014-6.281 2.831-6.281 6.305v0 1.859h-1.458c-0.665 0.002-1.203 0.54-1.206 1.205v11.483c0.002 0.665 0.541 1.203 1.205 1.205h15.528c0.665-0.002 1.203-0.54 1.205-1.205v-11.485c-0.003-0.664-0.541-1.2-1.205-1.203h-1.46v-1.859c-0-3.482-2.823-6.305-6.305-6.305-0.008 0-0.017 0-0.025 0h0.001zM6.403 4.906c-0 0-0 0-0 0-0.609 0-1.103 0.494-1.103 1.103 0 0.313 0.13 0.596 0.34 0.797l0 0 2.962 2.437c0.188 0.156 0.431 0.25 0.696 0.25 0.002 0 0.003 0 0.004 0h-0v-0.002c0 0 0 0 0 0 0.608 0 1.1-0.493 1.1-1.1 0-0.341-0.155-0.646-0.399-0.848l-0.002-0.001-2.964-2.435c-0.177-0.126-0.397-0.201-0.635-0.201h-0zM25.617 4.889c-0.246 0.001-0.472 0.083-0.654 0.22l0.003-0.002-2.967 2.434c-0.247 0.203-0.402 0.509-0.402 0.851 0 0.608 0.493 1.101 1.101 1.101 0.266 0 0.51-0.094 0.701-0.252l-0.002 0.002 2.963-2.438c0.223-0.202 0.363-0.493 0.363-0.817 0-0.608-0.493-1.1-1.1-1.1-0.002 0-0.004 0-0.006 0h0zM15.989 1.004c-0.576 0.006-1.046 0.452-1.089 1.017l-0 0.004v3.775c0.004 0.605 0.495 1.094 1.1 1.094 0.604 0 1.095-0.487 1.1-1.090v-3.779c-0.044-0.573-0.52-1.021-1.1-1.021-0.004 0-0.007 0-0.011 0h0.001z"></path>
</svg>
<div>
Run Renew SSL
</div>
<!-- Loading Spinner -->
<div wire:loading wire:target="runRenewSSL" class="ml-2 spinner-border animate-spin h-5 w-5 border-t-2 dark:border-white border-primary-700 rounded-full"></div>
</div>
</div>
<div wire:click="runDomainRepair" class="repair-tool-action">
<svg xmlns="http://www.w3.org/2000/svg" width="50%" viewBox="0 0 24 24"><path fill="currentColor" d="M2 14a1 1 0 1 1-2 0a1 1 0 0 1 2 0" opacity="0.5"/><path fill="currentColor" d="M6.719 10.262a1.73 1.73 0 0 0-2.458 0a1.757 1.757 0 0 0 0 2.476a1.73 1.73 0 0 0 2.458 0a.75.75 0 0 1 1.062 1.059a3.23 3.23 0 0 1-4.583 0a3.257 3.257 0 0 1 0-4.594a3.23 3.23 0 0 1 4.583 0a.75.75 0 0 1-1.062 1.059M8.5 11.5a3.25 3.25 0 1 1 6.5 0a3.25 3.25 0 0 1-6.5 0m3.25-1.75a1.75 1.75 0 1 0 0 3.5a1.75 1.75 0 0 0 0-3.5M18 8.25c-1.395 0-2.5 1.15-2.5 2.536V14a.75.75 0 0 0 1.5 0v-3.214c0-.587.462-1.036 1-1.036s1 .45 1 1.036V14a.75.75 0 0 0 1.5 0v-3.214c0-.587.462-1.036 1-1.036s1 .45 1 1.036V14a.75.75 0 0 0 1.5 0v-3.214C24 9.4 22.895 8.25 21.5 8.25c-.686 0-1.301.278-1.75.725A2.47 2.47 0 0 0 18 8.25"/></svg>
<div>
Run Domain Repair
</div>
</div>
</div>
</div>

View file

@ -147,32 +147,10 @@
<x-filament-panels::unsaved-action-changes-alert />
<div class="text-sm dark:text-white/40 text-center mb-4">
<div style="width: 700px; margin: 0 auto;">
PhyrePanel is currently in beta, so some features may not work as expected.
<br />
If you'd like to support development and help resolve issues, consider <a href="https://www.buymeacoffee.com/phyre">buying a coffee. </a>
</div>
@php
$primaryColor = 'FFDD00';
try {
if (setting('general.brand_primary_color')) {
$primaryColor = setting('general.brand_primary_color');
$primaryColor = str_replace('#', '', $primaryColor);
}
} catch (\Exception $e) {
//
}
@endphp
<a href="https://www.buymeacoffee.com/phyre" style="display: inline-block;margin: 15px 0px;">
<img src="https://img.buymeacoffee.com/button-api/?text=Support Phyre Panel&emoji=&slug=phyre&button_colour={{$primaryColor}}&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff" alt="Support Phyre Panel" style="height: 30px !important; ">
</a>
© 2023-2024 <a href="#" class="hover:underline"> PHYRE - Web Hosting Panel </a>. All Rights Reserved.
<br />
<div>
© 2023-2024 <a href="#" class="hover:underline"> PHYRE - Web Hosting Panel </a>. All Rights Reserved.
<br />
<br />
</div>
<a href="https://www.buymeacoffee.com/phyre" style="display: inline-block;margin: 15px 0px;">
<img src="https://img.buymeacoffee.com/button-api/?text=Support Phyre Panel&emoji=&slug=phyre&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff" alt="Support Phyre Panel" style="height: 30px !important; ">
</a>
</div>
</div>

View file

@ -34,24 +34,3 @@ Route::get('backup/download', [\App\Http\Controllers\BackupDownloadController::c
Route::get('/customers/{id}/login-with-token', [\App\Http\Controllers\Api\CustomersController::class, 'loginWithToken'])
->name('customers.login-with-token');
//
//
//Route::get('module/{module}/icon', function ($module) {
//
// $moduleInfo = \App\ModulesManager::getModuleInfo($module);
// if (empty($moduleInfo)) {
// return response()->json(['error' => 'Module not found'], 404);
// }
// if (!isset($moduleInfo['logoIcon'])) {
// return response()->json(['error' => 'Module icon not found'], 404);
// }
// if (!file_exists(base_path($moduleInfo['logoIcon']))) {
// return response()->json(['error' => 'Module icon not found'], 404);
// }
//
// $icon = file_get_contents(base_path($moduleInfo['logoIcon']));
//
// return response($icon)->header('Content-Type', 'image/svg+xml');
//
//
//})->name('module.icon.render');

View file

@ -9,36 +9,4 @@ export default {
'./vendor/filament/**/*.blade.php',
'./vendor/jaocero/radio-deck/resources/views/**/*.blade.php',
],
theme: {
extend: {
colors: {
secondary: {
50: 'rgba(var(--secondary-50), <alpha-value>)',
100: 'rgba(var(--secondary-100), <alpha-value>)',
200: 'rgba(var(--secondary-200), <alpha-value>)',
300: 'rgba(var(--secondary-300), <alpha-value>)',
400: 'rgba(var(--secondary-400), <alpha-value>)',
500: 'rgba(var(--secondary-500), <alpha-value>)',
600: 'rgba(var(--secondary-600), <alpha-value>)',
700: 'rgba(var(--secondary-700), <alpha-value>)',
800: 'rgba(var(--secondary-800), <alpha-value>)',
900: 'rgba(var(--secondary-900), <alpha-value>)',
950: 'rgba(var(--secondary-950), <alpha-value>)',
},
polarnight: {
50: "#e5e9f0", // Lightest (pale version of #2E3440)
100: "#d1d7e0", // Light shade of #2E3440
200: "#a7b1c5", // Lighter shade of #3B4252
300: "#8c9ab3", // Lighter shade of #3B4252
400: "#71829b", // Lighter shade of #434C5E
500: "#4c566a", // Base color (#4C566A)
600: "#434c5e", // Darker shade of #434C5E
700: "#3b4252", // Darker shade of #3B4252
800: "#2e3440", // Base color (#2E3440)
900: "#232831", // Darker shade of #2E3440
950: "#1b2027" // Darkest shade, almost black
},
},
},
},
};

View file

@ -54,9 +54,9 @@ dpkg -i /usr/local/phyre/update/nginx/phyre-nginx-1.24.0-$OS_LOWER-$OS_VERSION.d
printf "Updating the panel...\n"
wget https://raw.githubusercontent.com/PhyreApps/PhyrePanelNGINX/main/compilators/debian/nginx/nginx.conf -O /usr/local/phyre/nginx/conf/nginx.conf
#
# mkdir -p /usr/local/phyre/ssl
# cp /usr/local/phyre/web/server/ssl/phyre.crt /usr/local/phyre/ssl/phyre.crt
# cp /usr/local/phyre/web/server/ssl/phyre.key /usr/local/phyre/ssl/phyre.key
mkdir -p /usr/local/phyre/ssl
cp /usr/local/phyre/web/server/ssl/phyre.crt /usr/local/phyre/ssl/phyre.crt
cp /usr/local/phyre/web/server/ssl/phyre.key /usr/local/phyre/ssl/phyre.key
systemctl restart phyre
#systemctl status phyre