├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .readthedocs.yaml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── app.py ├── auto_build_docs.sh ├── docs ├── Makefile ├── _static │ └── custom.css ├── alerts.rst ├── api_endpoints.rst ├── architecture.rst ├── assets │ └── images │ │ ├── architecture.jpg │ │ ├── screenshot_001.png │ │ ├── screenshot_002.png │ │ ├── screenshot_003.png │ │ ├── screenshot_004.png │ │ ├── screenshot_005.png │ │ ├── screenshot_006.png │ │ ├── screenshot_007.png │ │ └── screenshot_008.png ├── conf.py ├── configure_alert.rst ├── configure_central_server.rst ├── features_toggles.rst ├── general_settings.rst ├── index.rst ├── installation.rst ├── introduction.rst ├── make.bat ├── other_useful_commands.rst ├── profile_management.rst ├── prometheus_setup.rst ├── requirements.txt ├── security_analysis.rst ├── system_info.rst ├── systemguard_process_manager.rst ├── user_management.rst ├── user_settings.rst └── utilities.rst ├── prometheus_config └── alert_rules.yml ├── requirements.txt ├── send_alert.py ├── setup.sh ├── setup_nginx.sh └── src ├── __int__.py ├── alert_manager ├── __init__.py ├── discord_alert.py ├── email_alert.py ├── google_chat_alert.py ├── slack_alert.py ├── team_alert.py └── telegram_alert.py ├── assets └── predefine_user.json ├── background_task ├── __init__.py ├── external_monitoring.py ├── log_system_info.py └── monitor_website.py ├── config.py ├── docs ├── README.md ├── Release.md ├── email_alerts.md ├── future_plans.md ├── images │ └── SystemGuard-Architecture.jpg ├── installation.md ├── installation_flow_chart.md ├── release_instrunctions.md └── upcoming_feature.md ├── helper.py ├── logger.py ├── models ├── __init__.py ├── alert_data_models.py ├── application_general_settings.py ├── base_model.py ├── dashboard_netowrk.py ├── monitored_website.py ├── network_speed_test_result.py ├── notification_settings.py ├── page_toggle_settings.py ├── prometheus_model.py ├── smtp_configuration.py ├── system_information.py ├── user_card_settings.py ├── user_dashboard_settings.py └── user_profile.py ├── routes ├── __init__.py ├── alert_route.py ├── api.py ├── auth.py ├── cpu_info.py ├── dashboard.py ├── dashboard_network.py ├── disk_info.py ├── error_handlers.py ├── experimental.py ├── firewall.py ├── graphs.py ├── health.py ├── helper │ ├── __init__.py │ ├── common_helper.py │ ├── firewall_helper.py │ ├── network_helper.py │ ├── notification_helper.py │ ├── prometheus_helper.py │ └── unique_id_helper.py ├── memory_info.py ├── network_info.py ├── other.py ├── ping.py ├── process_info.py ├── profile.py ├── prometheus.py ├── settings.py ├── smtp_email_config.py ├── speedtest.py ├── update_webhooks.py └── user_management.py ├── scripts ├── dashboard.sh ├── initialization │ └── init_alertmanager.sh ├── install_docker_centos.sh ├── install_influx.sh ├── install_miniconda.sh ├── setup_docker.sh ├── start_alertmanager.sh ├── start_prometheus.sh ├── update_prometheus.sh └── utils │ ├── cpu_stress.py │ ├── line_counter.py │ ├── locustfile.py │ ├── memory_stress.py │ ├── minify.py │ └── missing_dependency.py ├── static ├── css │ ├── 403.css │ ├── 404.css │ ├── about.css │ ├── active_alerts.css │ ├── add_server.css │ ├── alert_history.css │ ├── alertmanager_status.css │ ├── card.css │ ├── change_password.css │ ├── change_user.css │ ├── control_tab.css │ ├── create_user.css │ ├── dashboard_network.css │ ├── edit_profile.css │ ├── edit_server.css │ ├── edit_website.css │ ├── error.css │ ├── experimental.css │ ├── external_monitoring.css │ ├── firewall.css │ ├── footer.css │ ├── graphs.css │ ├── login.css │ ├── new_alert_rules.css │ ├── os_info.css │ ├── ping.css │ ├── process.css │ ├── refresher.css │ ├── scan.css │ ├── send_email.css │ ├── settings.css │ ├── show_alert.css │ ├── signup.css │ ├── smtp_config.css │ ├── speedtest_error.css │ ├── style.css │ ├── tab_navigation.css │ ├── targets.css │ ├── terminal.css │ ├── terms.css │ ├── time_filter.css │ ├── update_card.css │ ├── update_webhooks.css │ ├── utility.css │ ├── view_profile.css │ ├── view_rules.css │ └── view_users.css └── js │ ├── bootTime.js │ ├── cardChart.js │ ├── checkPassword.js │ ├── graphs.js │ ├── main.js │ ├── portUrlToggle.js │ ├── refreshCardData.js │ ├── refreshPage.js │ ├── targets.js │ ├── terminal.js │ ├── update.js │ └── updateRefreshInterval.js ├── templates ├── alerts │ ├── active_alerts.html │ ├── alert_history.html │ ├── alertmanager_status.html │ ├── new_alert_rule.html │ └── show_alerts.html ├── auths │ ├── login.html │ └── signup.html ├── base │ └── base.html ├── card_comp │ ├── battery │ │ └── percentage.html │ ├── cpu │ │ ├── core.html │ │ ├── critical_temp.html │ │ ├── current_temp.html │ │ ├── frequency.html │ │ ├── highest_temp.html │ │ └── usages.html │ ├── disk │ │ ├── free.html │ │ ├── total.html │ │ ├── usage.html │ │ └── used.html │ ├── memory │ │ ├── available.html │ │ ├── dashboard_memory.html │ │ ├── swap_free.html │ │ ├── swap_total.html │ │ ├── swap_used.html │ │ ├── usage.html │ │ └── used.html │ ├── network │ │ ├── ipv4_ip.html │ │ ├── ipv6_ip.html │ │ ├── packets_received.html │ │ ├── packets_sent.html │ │ └── stats.html │ ├── other │ │ ├── os_info.html │ │ ├── server_node.html │ │ ├── server_time.html │ │ ├── speedtest.html │ │ ├── uptime.html │ │ └── username.html │ └── selector │ │ └── refresh_button.html ├── dashboard │ └── homepage.html ├── email_templates │ ├── admin_login_alert.html │ ├── alert_template.html │ ├── deletion_email.html │ ├── login.html │ ├── logout.html │ ├── new_user_alert.html │ ├── new_user_create.html │ ├── notification_alert.html │ ├── process_killed.html │ ├── server_up.html │ ├── speedtest_result.html │ ├── website_monitor_status.html │ └── welcome.html ├── error │ ├── 400.html │ ├── 403.html │ ├── 404.html │ ├── 405.html │ ├── 500.html │ ├── 502.html │ ├── 503.html │ └── speedtest_error.html ├── experimental │ └── scan.html ├── ext │ ├── footer.html │ ├── header.html │ ├── message.html │ └── navbar.html ├── firewall │ └── firewall.html ├── graphs │ ├── historical_alerts_metrics.html │ └── historical_system_metrics.html ├── info_pages │ ├── cpu_info.html │ ├── disk_info.html │ ├── memory_info.html │ ├── network_info.html │ ├── os_info.html │ └── process.html ├── network │ └── dashboard_network.html ├── other │ ├── about.html │ ├── send_email.html │ ├── smtp_config.html │ ├── speedtest_result.html │ ├── terminal.html │ ├── terms.html │ ├── update_webhooks.html │ └── view_rules.html ├── ping │ ├── edit_website.html │ └── ping.html ├── prometheus │ ├── external_monitoring.html │ └── targets.html ├── settings │ ├── card_toggles.html │ ├── control_panel.html │ ├── general_settings.html │ ├── page_toggles.html │ ├── user_settings.html │ └── utility.html └── users │ ├── change_password.html │ ├── change_user.html │ ├── create_user.html │ ├── edit_profile.html │ ├── view_profile.html │ └── view_users.html └── utils.py /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | 12 | A clear and concise description of what the bug is. 13 | 14 | **To Reproduce** 15 | 16 | Steps to reproduce the behavior: 17 | 18 | **Expected behavior** 19 | 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Screenshots** 23 | 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **(please complete the following information):** 27 | 28 | - OS: [e.g. iOS] 29 | - Browser [e.g. chrome, safari] 30 | - Systemguard version [e.g. 22] 31 | 32 | **Additional context** 33 | 34 | Add any other context about the problem here. 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | 12 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 13 | 14 | **Describe the solution you'd like** 15 | 16 | A clear and concise description of what you want to happen. 17 | 18 | **Describe alternatives you've considered** 19 | 20 | A clear and concise description of any alternative solutions or features you've considered. 21 | 22 | **Additional context** 23 | 24 | Add any other context or screenshots about the feature request here. 25 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file for Sphinx projects 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | # Required 5 | version: 2 6 | 7 | # Set the OS, Python version and other tools you might need 8 | build: 9 | os: ubuntu-22.04 10 | tools: 11 | python: "3.12" 12 | 13 | # Build documentation in the "docs/" directory with Sphinx 14 | sphinx: 15 | configuration: docs/conf.py 16 | 17 | # Optionally build your docs in additional formats such as PDF and ePub 18 | formats: 19 | - pdf 20 | - epub 21 | 22 | python: 23 | install: 24 | - requirements: docs/requirements.txt -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Deepak Raj 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from src.config import app 2 | from src import routes 3 | from src.background_task import start_background_tasks 4 | 5 | # Start the background tasks 6 | start_background_tasks() 7 | 8 | if __name__ == "__main__": 9 | app.run(host="0.0.0.0", port=5001, debug=True) 10 | -------------------------------------------------------------------------------- /auto_build_docs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Set the directories for your Sphinx documentation source and build 4 | SOURCE_DIR="docs" 5 | BUILD_DIR="build" 6 | PORT=5051 7 | 8 | # remove the build directory 9 | rm -rf "$BUILD_DIR" 10 | 11 | # Check if sphinx-autobuild is installed 12 | if ! command -v sphinx-autobuild &> /dev/null 13 | then 14 | echo "sphinx-autobuild could not be found, installing it now..." 15 | pip install sphinx-autobuild 16 | fi 17 | 18 | # Run sphinx-autobuild with the source and build directories 19 | echo "Starting auto-reload for Sphinx documentation..." 20 | sphinx-autobuild "$SOURCE_DIR" "$BUILD_DIR" --open-browser --port "$PORT" 21 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/_static/custom.css: -------------------------------------------------------------------------------- 1 | /* Navbar customization */ 2 | .navbar .toc { 3 | display: none; /* This will hide the TOC */ 4 | } 5 | .navbar a { 6 | color: #007bff; /* Link color */ 7 | padding: 10px 15px; /* Padding around links */ 8 | } 9 | 10 | .navbar a:hover { 11 | background-color: #e2e6ea; /* Background color on hover */ 12 | color: #0056b3; /* Darker link color on hover */ 13 | } 14 | 15 | .navbar .navbar-brand { 16 | font-weight: bold; /* Bold brand name */ 17 | } 18 | 19 | /* Responsive adjustments */ 20 | @media (max-width: 768px) { 21 | .navbar { 22 | flex-direction: column; /* Stack items vertically on small screens */ 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /docs/api_endpoints.rst: -------------------------------------------------------------------------------- 1 | API Endpoints Overview 2 | ======================= 3 | 4 | System Information 5 | ------------------ 6 | - **Endpoint**: ``/api/v1/system-info`` 7 | - **Method**: ``GET`` 8 | - **Description**: Retrieve system metrics and performance data. 9 | 10 | Historical Metrics Data 11 | ----------------------- 12 | - **Endpoint**: ``/api/v1/prometheus/graphs_data/targets`` 13 | - **Method**: ``GET`` 14 | - **Description**: Fetch historical metrics data for specific targets. 15 | 16 | SystemGuard/Prometheus Targets 17 | ------------------------------ 18 | - **Endpoint**: ``/api/v1/targets`` 19 | - **Method**: ``GET`` 20 | - **Description**: Retrieve a list of all monitoring targets in SystemGuard/Prometheus. 21 | 22 | Refresh Interval 23 | ---------------- 24 | - **Endpoint**: ``/api/v1/refresh-interval`` 25 | - **Method**: ``GET`` 26 | - **Description**: Get the current refresh interval. 27 | 28 | - **Endpoint**: ``/api/v1/refresh-interval`` 29 | - **Method**: ``POST`` 30 | - **Description**: Set or update the refresh interval. 31 | 32 | OS Information 33 | -------------- 34 | - **Endpoint**: ``/api/v1/os-info`` 35 | - **Method**: ``GET`` 36 | - **Description**: Get information about the operating system. 37 | 38 | Prometheus Configuration 39 | ------------------------ 40 | - **Endpoint**: ``/api/v1/prometheus/config`` 41 | - **Method**: ``GET`` 42 | - **Description**: Retrieve the current Prometheus configuration. 43 | 44 | - **Method**: ``POST`` 45 | - **Description**: Update the Prometheus configuration. 46 | 47 | Prometheus Rules 48 | ---------------- 49 | - **Endpoint**: ``/api/v1/prometheus/rules`` 50 | - **Method**: ``GET`` 51 | - **Description**: Get the defined Prometheus rules. 52 | 53 | - **Method**: ``POST`` 54 | - **Description**: Update the Prometheus rules. 55 | 56 | Prometheus Ready 57 | ---------------- 58 | - **Endpoint**: ``/api/v1/prometheus/ready`` 59 | - **Method**: ``GET`` 60 | - **Description**: Check if Prometheus is ready. 61 | -------------------------------------------------------------------------------- /docs/assets/images/architecture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/docs/assets/images/architecture.jpg -------------------------------------------------------------------------------- /docs/assets/images/screenshot_001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/docs/assets/images/screenshot_001.png -------------------------------------------------------------------------------- /docs/assets/images/screenshot_002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/docs/assets/images/screenshot_002.png -------------------------------------------------------------------------------- /docs/assets/images/screenshot_003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/docs/assets/images/screenshot_003.png -------------------------------------------------------------------------------- /docs/assets/images/screenshot_004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/docs/assets/images/screenshot_004.png -------------------------------------------------------------------------------- /docs/assets/images/screenshot_005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/docs/assets/images/screenshot_005.png -------------------------------------------------------------------------------- /docs/assets/images/screenshot_006.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/docs/assets/images/screenshot_006.png -------------------------------------------------------------------------------- /docs/assets/images/screenshot_007.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/docs/assets/images/screenshot_007.png -------------------------------------------------------------------------------- /docs/assets/images/screenshot_008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/docs/assets/images/screenshot_008.png -------------------------------------------------------------------------------- /docs/configure_central_server.rst: -------------------------------------------------------------------------------- 1 | Configure the Central Server 2 | =========================== 3 | 4 | To configure the central server, you need to set up Prometheus to access data and metrics from other servers where SystemGuard is installed. 5 | 6 | Steps to Configure: 7 | 8 | 1. Navigate to **SystemGuard Central** and click on **Configure Targets for SystemGuard**. 9 | 10 | 2. To add a new target, provide the following details: 11 | 12 | - **Job Name**: Enter a descriptive job name (e.g., `dev server`). 13 | - **Target URL**: Specify the target URL (e.g., `dev-server-ip:8000`). 14 | - **Scrape Interval**: Set the scrape interval (e.g., `10s`). 15 | - **Username**: Enter the Prometheus username for that server (any valid login will work). 16 | - **Password**: Enter the Prometheus password for that server (any valid login will work). 17 | 18 | 3. After entering the target details, click on the **Add Target** button to save the target. 19 | 20 | 4. Next, click on **Update Prometheus** to apply the changes in Prometheus. 21 | 22 | 5. Verify the changes in **Prometheus** or the **Dashboard Network** (within SystemGuard) to ensure everything is functioning correctly. 23 | -------------------------------------------------------------------------------- /docs/features_toggles.rst: -------------------------------------------------------------------------------- 1 | Toggles 2 | ======= 3 | 4 | Page Toggles 5 | ------------ 6 | 7 | You can enable/disable page features using the following toggles: 8 | 9 | .. list-table:: 10 | :widths: 30 70 11 | :header-rows: 1 12 | 13 | * - Toggle 14 | - Description 15 | * - Dashboard Network 16 | - Dashboard Network to track the target network. 17 | * - CPU Information 18 | - CPU Information to track the target CPU. 19 | * - Memory Information 20 | - Memory Information to track the target memory. 21 | * - Disk Information 22 | - Disk Information to track the target disk. 23 | * - Network Information 24 | - Network Information to track the target network. 25 | * - Process Information 26 | - Process Information to track the target process. 27 | 28 | 29 | Card Toggles 30 | ------------ 31 | 32 | you can enable/disable card features using the following toggles: 33 | 34 | .. list-table:: 35 | :widths: 20 80 36 | :header-rows: 1 37 | 38 | * - Toggle 39 | - Description 40 | * - User Card 41 | - Card to show the user information. 42 | * - Server Card 43 | - Card to show the server information. 44 | * - Battery Card 45 | - Card to show the battery information. 46 | * - CPU Core Card 47 | - Card to show the CPU core information. 48 | * - CPU Usage Card 49 | - Card to show the CPU usage information. 50 | * - CPU Temp Card 51 | - Card to show the CPU temperature information. 52 | * - Dashboard Memory Card 53 | - Card to show the SystemGuard memory consumption. 54 | * - Memory Usage Card 55 | - Card to show the memory usage information. 56 | * - Disk Usage Card 57 | - Card to show the disk usage information. 58 | * - System Uptime Card 59 | - Card to show the system uptime information. 60 | * - Network Statistic Card 61 | - Card to show the network statistics information. 62 | * - Speedtest Card 63 | - Card to show the network speed test information. 64 | 65 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. rst-class:: hide-header 2 | 3 | Welcome to SystemGuard's documentation! 4 | ======================================= 5 | 6 | 7 | .. toctree:: 8 | :maxdepth: 2 9 | 10 | introduction.rst 11 | installation.rst 12 | architecture.rst 13 | other_useful_commands.rst 14 | prometheus_setup.rst 15 | configure_alert.rst 16 | configure_central_server.rst 17 | systemguard_process_manager.rst 18 | general_settings.rst 19 | user_settings.rst 20 | features_toggles.rst 21 | security_analysis.rst 22 | utilities.rst 23 | user_management.rst 24 | profile_management.rst 25 | system_info.rst 26 | alerts.rst 27 | api_endpoints.rst 28 | -------------------------------------------------------------------------------- /docs/introduction.rst: -------------------------------------------------------------------------------- 1 | introduction 2 | ============== 3 | 4 | System Guard is a Flask app designed to monitor server stats such as 5 | CPU, Memory, Disk, and Network. It also provides real-time monitoring 6 | capabilities which can be useful for system administrators, developers, 7 | and DevOps engineers to keep track of their server’s performance and 8 | troubleshoot issues. The app uses the ``psutil`` library to retrieve 9 | system stats and the ``speedtest-cli`` library to perform a network 10 | speed test. 11 | 12 | Features 🚀 13 | ----------- 14 | 15 | - Lightweight, open-source, and free to use with a straightforward 16 | installation process, out-of-the-box monitoring solution. 17 | - Capable of monitoring core server metrics like CPU, memory, disk 18 | usage, and network traffic. 19 | - Analyze fluctuations in server performance with historical data 20 | displayed as charts. 21 | - Centralized control panel for monitor/manage/analyze the fleet of 22 | servers. 23 | - Role-Based Access Control (RBAC) for managing user permissions. 24 | - Includes built-in security features such as authentication for login, 25 | logout, and signup. 26 | - Analuze the network speed with the built-in speed test feature. 27 | - Anaylze the suspicious processes and terminate them with a single 28 | click. 29 | - Anaylze the network statistics with the built-in network statistics 30 | feature. 31 | - Anaylze the subnet for security vulnerabilities with the built-in 32 | security analysis feature. 33 | - Option to download historical data in CSV format for detailed 34 | analysis (upcoming feature). 35 | - Role-based dashboards tailored for Developer, Admin, IT Manager, and 36 | Manager roles (upcoming feature). 37 | - Update security updates with a single click or automatically update 38 | to the latest version to simplify maintenance. 39 | - Real-time monitoring capabilities to keep track of server performance 40 | 41 | .. note:: 42 | By default, SystemGuard is running on 5050 port and prometheus is running on 9090 port. 43 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.https://www.sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/profile_management.rst: -------------------------------------------------------------------------------- 1 | Profile Management 2 | ================== 3 | 4 | The **Profile Management** section in SystemGuard allows users to view and manage their account details, update settings, and perform actions like enabling super admin privileges. 5 | 6 | User Information 7 | ---------------- 8 | 9 | In this section, users can view their basic profile details: 10 | 11 | - **Username**: Displays the user's unique identifier in the system. 12 | - **Email**: Displays the user's email address. This is used for account communication and notifications. 13 | - **User Level**: Displays the user’s access level (e.g., `admin`). Admins have full system access, while regular users have limited access. 14 | - **Email Alerts**: Displays whether email alerts are enabled (`True` if enabled). 15 | - **Role**: Displays the user's role in the organization (e.g., `Software Developer`). 16 | 17 | Profile Actions 18 | --------------- 19 | 20 | Users have several actions they can perform within the Profile Management section: 21 | 22 | - **Edit Profile**: Allows users to update their personal information, including their email, role, and other relevant details. 23 | - **Change Password**: Enables users to change their current password by entering their existing password and specifying a new one. 24 | - **Delete Profile**: This option allows users to delete their profile from the system. This action is irreversible and should be done with caution. 25 | - **Logout**: Logs the user out of the SystemGuard dashboard, ending the current session. 26 | 27 | Super Admin Privileges 28 | ---------------------- 29 | 30 | - **Enter Sudo Password**: For admin users, this option allows you to elevate privileges by entering a sudo password. This is necessary for performing critical actions that require additional authentication. 31 | - **Enable Super Admin**: This option enables the super admin mode, granting the user the highest level of system access for tasks such as user management, system configurations, and critical system updates. 32 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | pydata_sphinx_theme 3 | -------------------------------------------------------------------------------- /docs/security_analysis.rst: -------------------------------------------------------------------------------- 1 | Security Analysis 2 | ================= 3 | 4 | SystemGuard includes a built-in **Security Analysis** feature designed to scan subnets for potential security vulnerabilities. This tool is essential for system administrators, developers, and DevOps engineers to proactively identify and address security risks within their network. 5 | 6 | 1. **Scan Subnet for Vulnerabilities** 7 | 8 | To perform a security scan of the subnet, follow these steps: 9 | 10 | - Go to the **Security Tools** section in the SystemGuard dashboard. 11 | - Select the **Security Analysis** tab. 12 | 13 | 2. **Subnet Device and Open Port Scan** 14 | 15 | You can scan the subnet to discover devices and their associated open ports: 16 | 17 | - Click on the **Scan** button to begin scanning the subnet. 18 | - The scan results will appear as a table displaying: 19 | 20 | - **IP Address** of each device 21 | - **Hostname** 22 | - A button to **View Open Ports** for each device. 23 | 24 | 3. **View Open Ports for a Specific Device** 25 | 26 | To check the open ports of a particular device: 27 | 28 | - Enter the **IP address** of the device in the search bar. 29 | - Click the **Scan Ports** button to display the open ports for that device. 30 | 31 | This process allows you to efficiently monitor your network's security status and take appropriate actions to mitigate vulnerabilities. 32 | 33 | 4. **Enable/Disable Port** 34 | 35 | You can enable or disable a port for a specific device: 36 | 37 | - Click on the **Firewall** under the **Security Tools** section. 38 | - Enter the `Sudo Password` to go in ``SuperAdmin`` Mode. 39 | - Check the open ports for the local device. 40 | - Enter the `port number`, `protocol` and `action` to enable or disable the port. 41 | 42 | The above security features are designed to enhance the security posture of your network and protect your systems from potential threats 43 | and it's powered by `nmap` and `iptables` tools. 44 | -------------------------------------------------------------------------------- /docs/system_info.rst: -------------------------------------------------------------------------------- 1 | System Info 2 | =========== 3 | 4 | System Info tab inside the admin panel provide the information about the system, systemGuard and the option to update the systemGuard app. 5 | 6 | Show OS Info 7 | ------------ 8 | 9 | This option will show the information about the operating system. The information includes the following: 10 | 11 | - OS Name 12 | - OS Version 13 | - OS Full Name 14 | - OS Codename 15 | - Kernel Version 16 | - Operating System 17 | 18 | 19 | About SystemGuard 20 | ----------------- 21 | 22 | This option will show the information about the SystemGuard. The information includes the following: 23 | 24 | - SystemGuard Version 25 | - SystemGuard Build 26 | - SystemGuard License 27 | - SystemGuard Year 28 | - SystemGuard Author 29 | - Installation Method 30 | - Update status 31 | - Contact Support 32 | 33 | Update SystemGuard 34 | ------------------ 35 | 36 | This option will update the SystemGuard app to the latest version. 37 | 38 | .. note:: 39 | The update process will not affect the existing data. 40 | -------------------------------------------------------------------------------- /docs/systemguard_process_manager.rst: -------------------------------------------------------------------------------- 1 | SystemGuard Process Manager 2 | =========================== 3 | 4 | SystemGuard Process Manager is a feature that allows you to manage the processes running on your system. 5 | You can view the list of processes, cpu usage, memory usage, and kill any process with a single click. 6 | 7 | To access the Process Manager, follow these steps: 8 | 9 | 1. Go to the **Process Manager** section in the SystemGuard navigation menu. 10 | 2. The Process Manager page will display a list of all running processes on your system. 11 | 3. You can view the following details for each process: 12 | - **Process Name**: Name of the process 13 | - **CPU Usages%**: CPU usage by the process 14 | - **Memory Usages%**: Memory usage by the process 15 | - **Process ID**: Process ID 16 | - **Action**: Actions you can perform on the process 17 | 18 | 4. You can filter the number of processes displayed by using the search bar. 19 | 5. To kill a process, click on the **Kill** button next to the process you want to terminate. 20 | 5. Some processes may require superuser privileges to kill. In such cases, 21 | you have to go in ``SuperAdmin`` mode by entering the `Sudo Password`. -------------------------------------------------------------------------------- /docs/user_management.rst: -------------------------------------------------------------------------------- 1 | User Management 2 | =============== 3 | 4 | Manage Users 5 | ~~~~~~~~~~~~ 6 | 7 | The User Management page provides functionality for overseeing users within the system. From this page, you can view, edit, and delete users, as well as create new user accounts. 8 | 9 | Create New User 10 | ~~~~~~~~~~~~~~~ 11 | 12 | To create a new user, click on the **Create New User** button. This action will open a form where you can input the user’s details. 13 | 14 | - **User Level**: Choose either **Admin** or **User**. An **Admin** user has full access to the system, while a **User** has restricted access. 15 | -------------------------------------------------------------------------------- /docs/user_settings.rst: -------------------------------------------------------------------------------- 1 | User Settings 2 | ============= 3 | 4 | The **User Settings** section provides options to customize and manage user-specific behavior and performance in SystemGuard. These settings allow you to define parameters for speed tests and dashboard refresh intervals. 5 | 6 | Speedtest Cooldown 7 | ~~~~~~~~~~~~~~~~~~ 8 | 9 | The **Speedtest Cooldown** setting determines the minimum time (in minutes) that must pass before a user can initiate another speedtest. This helps prevent excessive testing and ensures system resources are used efficiently. 10 | 11 | - **Cooldown Period**: Set the number of minutes required between speedtests. 12 | 13 | Number of Speedtests Allowed per Hour 14 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15 | 16 | The **Number of Speedtests Allowed per Hour** setting defines the maximum number of speedtests a user can perform within a one-hour period. This limit is essential for controlling bandwidth usage and avoiding network congestion. 17 | 18 | - **Limit**: Specify the maximum number of speedtests allowed per user, per hour. 19 | 20 | Refresh Interval 21 | ~~~~~~~~~~~~~~~~ 22 | 23 | The **Refresh Interval** setting controls the automatic refresh rate of the dashboard, specified in seconds. This allows you to determine how often the dashboard updates with the latest data, balancing performance and real-time information display. 24 | 25 | - **Interval**: Set the refresh interval in seconds for automatic dashboard updates. 26 | -------------------------------------------------------------------------------- /docs/utilities.rst: -------------------------------------------------------------------------------- 1 | Utilities 2 | ========= 3 | 4 | SystemGuard provides a set of utilities to help you manage the app and server. 5 | 6 | 1. Terminal 7 | 2. Shutdown/Restart 8 | 3. Send Email 9 | 4. SpeedTest 10 | 5. Website Pinger 11 | 6. External API Monitoring -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # Flask web framework 2 | Flask==3.0.3 3 | 4 | # System information and performance monitoring 5 | psutil==6.0.0 # Retrieves system metrics (CPU, memory, etc.) 6 | 7 | # Environment variable management 8 | python-dotenv==1.0.1 # Loads environment variables from .env file 9 | 10 | # WSGI HTTP server for production 11 | gunicorn==23.0.0 # Production server for running Flask applications 12 | 13 | # Flask extensions for database and session management 14 | flask-sqlalchemy==3.1.1 # SQLAlchemy ORM integration with Flask 15 | flask-login==0.6.3 # User session management (authentication) 16 | flask-session==0.8.0 # Server-side session storage 17 | flask-migrate==4.0.7 # Handles database migrations for Flask apps 18 | Flask-WTF==1.2.1 # Flask integration with WTForms 19 | Flask-Caching==2.3.0 # Caching extension for Flask 20 | Flask-Compress==1.15 # Compresses Flask HTTP responses (e.g., gzip) 21 | 22 | # File system monitoring 23 | watchdog==5.0.2 # Monitors filesystem events and changes 24 | 25 | # HTTP requests library 26 | requests==2.32.3 # Simplified HTTP requests for Python 27 | 28 | # Internet speed testing 29 | speedtest-cli==2.1.3 # CLI for testing internet speed 30 | 31 | # Prometheus client for monitoring and exposing metrics 32 | prometheus_client==0.20.0 # Exposes metrics for Prometheus to scrape 33 | 34 | # (Optional) InfluxDB client for writing metrics to InfluxDB 35 | # influxdb-client==1.46.0 # InfluxDB client for time-series data 36 | 37 | # YAML parsing and configuration handling 38 | pyyaml==6.0.2 # Reads and writes YAML configuration files 39 | 40 | # Asynchronous HTTP client/server framework 41 | aiohttp==3.10.7 # Async HTTP client for non-blocking requests 42 | -------------------------------------------------------------------------------- /send_alert.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import time 4 | from src.utils import get_ip_address 5 | 6 | def send_test_alert(alertmanager_url, alert_name, severity, instance): 7 | # Generate a unique alert name by appending the current timestamp 8 | unique_alert_name = f"{alert_name}_{int(time.time())}" 9 | 10 | # Define the alert data with the unique alert name 11 | alert_data = [ 12 | { 13 | "labels": { 14 | "alertname": unique_alert_name, 15 | "severity": severity, 16 | "instance": instance 17 | }, 18 | "annotations": { 19 | "description": f"This is a test alert generated at {time.strftime('%Y-%m-%d %H:%M:%S')}", 20 | "summary": "Test alert to check Slack notifications" 21 | } 22 | } 23 | ] 24 | 25 | # Send the POST request to Alertmanager 26 | try: 27 | response = requests.post( 28 | f"{alertmanager_url}/api/v2/alerts", 29 | headers={"Content-Type": "application/json"}, 30 | data=json.dumps(alert_data) 31 | ) 32 | 33 | # Log response details 34 | print(f"Response Code: {response.status_code}") 35 | print(f"Response Body: {response.text}") 36 | 37 | # Check the response 38 | if response.status_code == 202: 39 | print(f"Test alert '{unique_alert_name}' sent successfully!") 40 | else: 41 | print(f"Failed to send alert. Status code: {response.status_code}, Response: {response.text}") 42 | 43 | except Exception as e: 44 | print(f"An error occurred: {e}") 45 | 46 | # Example usage 47 | if __name__ == "__main__": 48 | ip_address = get_ip_address() 49 | print("IP Address:", ip_address) 50 | alertmanager_ip = ip_address 51 | alertmanager_port = "9093" 52 | alertmanager_url = f"http://{alertmanager_ip}:{alertmanager_port}" 53 | 54 | # Send a test alert with a unique name 55 | send_test_alert(alertmanager_url, "ScriptAlert", "critical", "instance_name") 56 | -------------------------------------------------------------------------------- /src/__int__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/src/__int__.py -------------------------------------------------------------------------------- /src/alert_manager/__init__.py: -------------------------------------------------------------------------------- 1 | from src.alert_manager.slack_alert import send_slack_alert 2 | from src.alert_manager.email_alert import send_smtp_email 3 | from src.alert_manager.discord_alert import send_discord_alert 4 | from src.alert_manager.team_alert import send_teams_alert 5 | from src.alert_manager.google_chat_alert import send_google_chat_alert 6 | 7 | __all__ = [ 8 | "send_slack_alert", 9 | "send_smtp_email", 10 | "send_discord_alert", 11 | "send_teams_alert", 12 | "send_google_chat_alert", 13 | ] 14 | -------------------------------------------------------------------------------- /src/alert_manager/discord_alert.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | import requests 3 | from src.logger import logger 4 | 5 | def send_discord_alert(webhook_url, alert_name, instance, severity, description, summary): 6 | """ 7 | Sends an alert to a Discord channel via a webhook. 8 | 9 | Args: 10 | webhook_url (str): The webhook URL for the Discord channel. 11 | alert_name (str): The name of the alert. 12 | instance (str): The instance associated with the alert. 13 | severity (str): The severity level of the alert (e.g., critical, warning, info). 14 | description (str): A detailed description of the alert. 15 | summary (str): A brief summary of the alert. 16 | 17 | Returns: 18 | bool: True if the alert was sent successfully, False otherwise. 19 | """ 20 | 21 | # Constructing the message to send to Discord 22 | color_dict = { 23 | "critical": 16711680, # Red 24 | "warning": 16776960, # Yellow 25 | "info": 65280 # Green 26 | } 27 | message = { 28 | "embeds": [ 29 | { 30 | "title": f"🚨 **{alert_name}** 🚨", 31 | "color": color_dict.get(severity, 0), 32 | "fields": [ 33 | {"name": "Instance", "value": instance, "inline": True}, 34 | {"name": "Severity", "value": severity, "inline": True}, 35 | {"name": "Description", "value": description, "inline": False}, 36 | {"name": "Summary", "value": summary, "inline": False} 37 | ], 38 | "footer": { 39 | "text": "System Guard Alert" 40 | }, 41 | "timestamp": datetime.utcnow().isoformat() 42 | } 43 | ] 44 | } 45 | 46 | # Send the POST request to the Discord webhook URL 47 | response = requests.post(webhook_url, json=message) 48 | 49 | # Check the response status 50 | if response.status_code != 204: 51 | logger.error(f"Failed to send alert to Discord: {response.status_code}, {response.text}") 52 | return False 53 | 54 | logger.info(f"Alert sent to Discord: {alert_name}") 55 | return True 56 | -------------------------------------------------------------------------------- /src/alert_manager/slack_alert.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | from datetime import datetime 4 | from src.logger import logger 5 | 6 | def send_slack_alert(webhook_url, alert_name, instance, severity, description, summary): 7 | """ 8 | Sends a formatted notification message to a Slack channel via webhook. 9 | 10 | Parameters: 11 | webhook_url (str): The Slack incoming webhook URL. 12 | alert_name (str): The name of the alert. 13 | instance (str): The instance related to the alert. 14 | severity (str): The severity level of the alert. 15 | description (str): A detailed description of the alert. 16 | summary (str): Summary of the alert. Default is "Prometheus Alert". 17 | color (str): Color of the message attachment. 18 | username (str): Username of the bot sending the message. 19 | icon_emoji (str): Emoji icon to show in Slack. 20 | """ 21 | 22 | # Build the payload 23 | color_dict = { 24 | "critical": "#ee1b1b", # Red 25 | "warning": "#eeee1b", # Yellow 26 | "info": "#16d119" # Green 27 | } 28 | 29 | payload = { 30 | "username": "SystemGuard Alert", 31 | "attachments": [ 32 | { 33 | "fallback": alert_name, 34 | "color": color_dict.get(severity, "gray"), 35 | "title": alert_name, 36 | "text": summary, 37 | "fields": [ 38 | {"title": "Instance", "value": instance, "short": True}, 39 | {"title": "Severity", "value": severity, "short": True}, 40 | {"title": "Description", "value": description, "short": False}, 41 | ], 42 | "footer": "System Metrics", 43 | "ts": f"{datetime.now().timestamp()} UTC" 44 | } 45 | ] 46 | } 47 | 48 | # Send the POST request to the Slack webhook URL 49 | response = requests.post(webhook_url, data=json.dumps(payload), headers={'Content-Type': 'application/json'}) 50 | 51 | # Check the response status 52 | if response.status_code != 200: 53 | raise Exception(f"Request to Slack failed with status code {response.status_code}, response: {response.text}") 54 | 55 | logger.info(f"Alert sent to Slack: {alert_name}") 56 | -------------------------------------------------------------------------------- /src/alert_manager/team_alert.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | from src.logger import logger 4 | 5 | 6 | def send_teams_alert(webhook_url, alert_name, instance, severity, description, summary): 7 | """ 8 | Sends a Prometheus alert to a Microsoft Teams channel using a webhook. 9 | 10 | Parameters: 11 | webhook_url (str): The webhook URL of the Teams channel. 12 | alert_name (str): The name of the alert (e.g., CPU usage high). 13 | instance (str): The instance where the alert occurred (e.g., the hostname or IP). 14 | severity (str): The severity level of the alert (e.g., critical, warning). 15 | description (str): Detailed description of the alert. 16 | summary (str): A brief summary of the alert (default is 'Prometheus Alert'). 17 | """ 18 | 19 | # Define the message payload 20 | message_payload = { 21 | "@type": "MessageCard", 22 | "@context": "https://schema.org/extensions", 23 | "summary": summary, 24 | "themeColor": "FF0000" if severity.lower() == "critical" else "FFD700", # Red for critical, Yellow for others 25 | "sections": [{ 26 | "activityTitle": f"**Alert: {alert_name}**", 27 | "facts": [ 28 | {"name": "Instance:", "value": instance}, 29 | {"name": "Severity:", "value": severity}, 30 | {"name": "Description:", "value": description} 31 | ], 32 | "text": description, 33 | "markdown": True 34 | }] 35 | } 36 | 37 | # Send the POST request to the webhook URL 38 | response = requests.post( 39 | webhook_url, 40 | headers={"Content-Type": "application/json"}, 41 | data=json.dumps(message_payload) 42 | ) 43 | 44 | # Check if the request was successful 45 | if response.status_code == 200: 46 | logger.info(f"Alert sent successfully to Microsoft Teams!") 47 | else: 48 | logger.error(f"Failed to send alert. Status code: {response.status_code}") 49 | logger.error(f"Response: {response.text}") 50 | -------------------------------------------------------------------------------- /src/alert_manager/telegram_alert.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from src.logger import logger 3 | 4 | def send_telegram_message(bot_token, chat_id, message): 5 | """ 6 | Sends a message to a Telegram chat using a bot. 7 | 8 | Parameters: 9 | bot_token (str): The API token for the bot from BotFather. 10 | chat_id (str or int): The chat ID where the message will be sent. 11 | message (str): The message content to send. 12 | """ 13 | # Define the URL for the Telegram API 14 | url = f"https://api.telegram.org/bot{bot_token}/sendMessage" 15 | 16 | # Define the payload for the message 17 | payload = { 18 | 'chat_id': chat_id, 19 | 'text': message 20 | } 21 | 22 | # Send the request 23 | response = requests.post(url, data=payload) 24 | 25 | # Check if the request was successful 26 | if response.status_code == 200: 27 | logger("Alert sent to Telegram.") 28 | else: 29 | logger.error(f"Failed to send message. Error code: {response.status_code}") 30 | -------------------------------------------------------------------------------- /src/assets/predefine_user.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "first_name": "John", 4 | "last_name": "Doe", 5 | "username": "admin", 6 | "email": "admin@gmail.com", 7 | "password": "admin", 8 | "user_level": "admin", 9 | "profession": "Software Developer", 10 | "receive_email_alerts": true 11 | }, 12 | { 13 | "first_name": "Db Admin", 14 | "last_name": "Admin", 15 | "username": "prometheus_admin", 16 | "email": "prometheus_admin@mail.com", 17 | "password": "prometheus_password", 18 | "user_level": "user", 19 | "profession": "Database Administrator", 20 | "receive_email_alerts": false 21 | } 22 | ] -------------------------------------------------------------------------------- /src/background_task/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | from src.background_task.monitor_website import start_website_monitoring 3 | from src.background_task.log_system_info import monitor_settings 4 | from src.background_task.external_monitoring import fetch_file_metrics_task 5 | from src.logger import logger 6 | 7 | 8 | 9 | def start_background_tasks(): 10 | """ 11 | Starts the background tasks for the application. 12 | """ 13 | if os.getenv('FLASK_ENV') == 'production': 14 | logger.info("Starting background tasks for production environment.") 15 | start_website_monitoring() 16 | fetch_file_metrics_task() 17 | monitor_settings() -------------------------------------------------------------------------------- /src/docs/README.md: -------------------------------------------------------------------------------- 1 | # Product Screenshots 📸 2 | 3 | ## Home Page 4 | 5 | ![screenshot_002](/src/static/images/screenshot_009.png) 6 | 7 | ## Cpu Info 8 | 9 | ![screenshot_003](/src/static/images/screenshot_003.png) 10 | 11 | ## Control Panel 12 | 13 | ![screenshot_004](/src/static/images/screenshot_004.png) 14 | 15 | ## Network Statistics 16 | 17 | ![screenshot_005](/src/static/images/screenshot_005.png) 18 | 19 | ## Running Processes 20 | 21 | ![screenshot_006](/src/static/images/screenshot_006.png) 22 | 23 | ## Security Analysis 24 | 25 | ![screenshot_007](/src/static/images/screenshot_007.png) 26 | 27 | ## Central Dashboard 28 | 29 | ![screenshot_008](/src/static/images/tracking.png) -------------------------------------------------------------------------------- /src/docs/email_alerts.md: -------------------------------------------------------------------------------- 1 | ## Email Feature 📧 2 | 3 | | Email Alert | Is implemented | who will get the email | 4 | | ---------------------------- | ------------------------- | --------------------------- | 5 | | Process Killed | Yes | Logged User | 6 | | Login | Yes | Admin User and Logged User | 7 | | Logout | Yes | Logged User | 8 | | Signup | Yes | Admin User & signed up User | 9 | | Create User | Yes | Admin User & Created User | 10 | | Delete User | No | Admin User & Deleted User | 11 | | Speed Test | Yes | Logged User | 12 | | Server Up | Yes | Admin User | 13 | | Notification Settings Change | Yes | Admin User | 14 | | Signup | Yes(few changes required) | Admin User & Logged User | 15 | | Website Monitoring | Yes | Input Email | 16 | | Server Down | No | Admin User | 17 | | Server Up | No | Admin User | -------------------------------------------------------------------------------- /src/docs/future_plans.md: -------------------------------------------------------------------------------- 1 | For a deep analysis of the **SystemGuard** project with the Firewall feature, here are some suggestions to improve: 2 | 3 | 1. **Code Structure**: 4 | - **Modularize the code**: Split large files into smaller, reusable modules (e.g., separate routes, services, and database logic). 5 | - **Error Handling**: Improve exception handling, especially for critical functions like firewall rule changes and system monitoring. 6 | - **Logging**: Implement structured logging for better debugging and system monitoring. 7 | 8 | 2. **Security**: 9 | - **Sanitize Inputs**: Ensure the inputs (such as firewall rules, ports) are validated and sanitized. 10 | - **Sudo Password Management**: Implement a time-based reset for `sudo` sessions. 11 | - **Rate Limiting**: Implement rate-limiting for operations that can modify system states, such as enabling/disabling ports. 12 | 13 | 3. **User Interface**: 14 | - **User Feedback**: Provide better feedback when operations succeed/fail, such as modal windows or alerts. 15 | - **Responsive Design**: Ensure all pages are fully responsive, especially for smaller devices. 16 | - **Modern CSS Framework**: Consider leveraging a CSS framework like Bootstrap or Tailwind for faster styling and grid layouts. 17 | 18 | 4. **Documentation**: 19 | - **Detailed Setup Instructions**: Improve the README with more detailed setup instructions, especially for the firewall feature. 20 | - **Code Comments**: Add comments explaining complex sections, such as how firewall rules are applied. 21 | 22 | 5. **Database Optimization**: 23 | - **Indexed Fields**: Add indexing to frequently queried fields to improve database performance. 24 | - **Optimize Queries**: Review database queries and optimize those that may impact performance during heavy usage. 25 | 26 | 6. **Testing**: 27 | - **Unit Tests**: Add unit and integration tests for each core feature, particularly the firewall management and monitoring features. 28 | - **CI/CD Pipeline**: Set up continuous integration to run tests automatically when new changes are made. 29 | 30 | These improvements will enhance maintainability, security, performance, and user experience. -------------------------------------------------------------------------------- /src/docs/images/SystemGuard-Architecture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/src/docs/images/SystemGuard-Architecture.jpg -------------------------------------------------------------------------------- /src/docs/release_instrunctions.md: -------------------------------------------------------------------------------- 1 | # SystemGuard Release Guidelines 2 | 3 | This document provides instructions for preparing and publishing a new release of SystemGuard. 4 | 5 | ## Versioning 6 | 7 | SystemGuard uses [Semantic Versioning](https://semver.org/) with the format `MAJOR.MINOR.PATCH`: 8 | 9 | - **MAJOR**: Increased for changes that break backward compatibility. 10 | - **MINOR**: Increased when new features are added. 11 | - **PATCH**: Increased for bug fixes and minor improvements. 12 | 13 | ## Release Notes 14 | 15 | Update the release notes in the `Release.md` file located in the `docs` directory. Include the following details: 16 | 17 | - **Version**: The version number for the release. 18 | - **Release Date**: The date the release is created. 19 | - **Status**: The release status (e.g., Pre-release, Stable, In Testing). 20 | - **Key Features**: Highlight the main features introduced in this release. 21 | - **Changelog**: A summary of changes included in the release. 22 | - **Upgrade Instructions**: Any specific steps or considerations for upgrading. 23 | - **Known Issues**: List any known problems or limitations. 24 | 25 | ## Release Process 26 | 27 | Follow these steps to release SystemGuard: 28 | 29 | - **Pre-release Versions**: Use a `-pre` suffix (e.g., `v1.0.4-pre`) for testing releases from the `dev` branch. 30 | - **Stable Versions**: Use a plain version number (e.g., `v1.0.4`) for production releases from the `production` branch. 31 | 32 | Before proceeding with a release, ensure the version numbers and flags are correctly set in the `config.py` file. 33 | 34 | ## Release Checklist 35 | 36 | Before creating a new release, make sure the following tasks are completed: 37 | 38 | - [ ] Update the version number in the `config.py` file. 39 | - [ ] Add and update release notes in the `Release.md` file. 40 | - [ ] Create a new branch for the release (e.g., `release-vn.n.n`). 41 | - [ ] Test the release in a staging environment. 42 | - [ ] Merge changes into the `production` branch. 43 | - [ ] Create a new release on GitHub. 44 | - [ ] Update the website with the new release details. 45 | - [ ] Revise the documentation to reflect the new release. 46 | -------------------------------------------------------------------------------- /src/docs/upcoming_feature.md: -------------------------------------------------------------------------------- 1 | ## Upcoming Features 📅 2 | 3 | | Feature | Stattus | 4 | | ----------------------------------------------------------------------- | ------- | 5 | | Receive notifications when system metrics cross predefined thresholds | pending | 6 | | Customizable dashboards for personalized server monitoring | pending | 7 | | Plugin support to enhance and extend SystemGuard's functionality | pending | 8 | | Generate and manage server logs for better tracking and troubleshooting | pending | 9 | | Monitor disk read/write speeds for performance insights | pending | 10 | | Check the current firewall status to ensure security | pending | 11 | | A dedicated website monitoring page for tracking uptime and performance | pending | 12 | | Track and save total network data sent/received in the database | pending | 13 | | Improve website monitor, save data in database with timestamp | pending | 14 | | Key-combinding to navigate through the website | pending | 15 | | Support for more server stats like GPU, etc. | pending | 16 | | Support for more Linux distros | pending | 17 | -------------------------------------------------------------------------------- /src/logger.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from logging.handlers import RotatingFileHandler 3 | import os 4 | 5 | ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 6 | LOG_DIR = os.path.join(ROOT_DIR, 'logs') 7 | # Create a logs directory if it doesn't exist 8 | os.makedirs(LOG_DIR, exist_ok=True) 9 | 10 | # Log Formatter with datetime, log level, and message 11 | formatter = logging.Formatter( 12 | '%(asctime)s - %(levelname)s - %(message)s', 13 | datefmt='%Y-%m-%d %H:%M:%S' 14 | ) 15 | 16 | # File handler for logging to a file 17 | file_handler = RotatingFileHandler( 18 | os.path.join(LOG_DIR, 'app_debug.log'), 19 | maxBytes=10 * 1024 * 1024, # 10 MB per log file 20 | backupCount=5 # Keep up to 5 old log files 21 | ) 22 | file_handler.setLevel(logging.DEBUG) 23 | file_handler.setFormatter(formatter) 24 | 25 | # Set up the logger 26 | logger = logging.getLogger(__name__) 27 | logger.setLevel(logging.DEBUG) # Log everything (DEBUG, INFO, WARNING, etc.) 28 | logger.addHandler(file_handler) 29 | 30 | # Optionally, add console output for real-time debugging (optional) 31 | # console_handler = logging.StreamHandler() 32 | # console_handler.setLevel(logging.INFO) 33 | # console_handler.setFormatter(formatter) 34 | # logger.addHandler(console_handler) 35 | 36 | -------------------------------------------------------------------------------- /src/models/alert_data_models.py: -------------------------------------------------------------------------------- 1 | from src.models.base_model import BaseModel 2 | from src.config import db 3 | 4 | 5 | # alert Data model to save the prometheus alert data 6 | class AlertDataModel(BaseModel): 7 | __tablename__ = "alert_data" 8 | 9 | id = db.Column(db.Integer, primary_key=True) 10 | alert_name = db.Column(db.String(255), nullable=False) 11 | instance = db.Column(db.String(255), nullable=False) 12 | severity = db.Column(db.String(255), nullable=False) 13 | description = db.Column(db.String(255), nullable=False) 14 | summary = db.Column(db.String(255), nullable=False) 15 | status = db.Column(db.String(255), nullable=True) 16 | start_time = db.Column(db.String(255), nullable=True) 17 | 18 | def __repr__(self): 19 | return f"" 20 | 21 | def serialize(self): 22 | return { 23 | 'id': self.id, 24 | 'alert_name': self.alert_name, 25 | 'instance': self.instance, 26 | 'severity': self.severity, 27 | 'description': self.description, 28 | 'summary': self.summary, 29 | 'status': self.status, 30 | 'start_time': self.start_time 31 | } 32 | -------------------------------------------------------------------------------- /src/models/application_general_settings.py: -------------------------------------------------------------------------------- 1 | from src.config import db 2 | from src.models.base_model import BaseModel 3 | 4 | class GeneralSettings(BaseModel): 5 | """ 6 | General settings model for the application 7 | --- 8 | Properties: 9 | - id: int 10 | - enable_alerts: if email alerts are enabled 11 | - timezone: the timezone of the system 12 | - enable_cache: if caching is enabled 13 | - is_logging_system_info: if system info is logged 14 | """ 15 | __tablename__ = 'general_settings' 16 | 17 | id = db.Column(db.Integer, primary_key=True) 18 | enable_alerts = db.Column(db.Boolean, default=True) 19 | timezone = db.Column(db.String(50), default='UTC') 20 | enable_cache = db.Column(db.Boolean, default=True) 21 | is_logging_system_info = db.Column(db.Boolean, default=True) 22 | -------------------------------------------------------------------------------- /src/models/base_model.py: -------------------------------------------------------------------------------- 1 | from src.config import db 2 | 3 | 4 | class BaseModel(db.Model): 5 | __abstract__ = True # This ensures that SQLAlchemy doesn't create a table for this class 6 | 7 | def save(self): 8 | db.session.add(self) 9 | db.session.commit() 10 | 11 | def delete(self): 12 | db.session.delete(self) 13 | db.session.commit() 14 | 15 | @classmethod 16 | def get_all(cls): 17 | return cls.query.all() 18 | 19 | @classmethod 20 | def get_by_id(cls, record_id): 21 | return cls.query.get(record_id) 22 | -------------------------------------------------------------------------------- /src/models/dashboard_netowrk.py: -------------------------------------------------------------------------------- 1 | from src.config import db 2 | from src.models.base_model import BaseModel 3 | 4 | 5 | class DashboardNetworkSettings(BaseModel): 6 | """ 7 | Dashboard network settings model for the application 8 | --- 9 | Properties: 10 | - id: int 11 | - name: the name of the dashboard 12 | - description: the description of the dashboard 13 | - ip_address: the IP address of the dashboard 14 | - port: the port of the dashboard 15 | - link: the link to the dashboard 16 | """ 17 | __tablename__ = "DashboardGroup" 18 | id = db.Column(db.Integer, primary_key=True) 19 | name = db.Column(db.String(50), unique=True, nullable=False) 20 | description = db.Column(db.String(150), nullable=True) 21 | ip_address = db.Column(db.String(50), nullable=True) 22 | port = db.Column(db.Integer, nullable=True) 23 | link = db.Column(db.String(150), nullable=True) 24 | 25 | def __repr__(self): 26 | return f"" 27 | -------------------------------------------------------------------------------- /src/models/monitored_website.py: -------------------------------------------------------------------------------- 1 | from src.config import db 2 | from src.models.base_model import BaseModel 3 | 4 | 5 | class MonitoredWebsite(BaseModel): 6 | """ 7 | Monitored website model for the application 8 | --- 9 | Properties: 10 | - id: int 11 | - name: the name of the website 12 | - ping_interval: the interval in seconds to ping the website 13 | - is_ping_active: if the website should be pinged 14 | - email_address: the email address to send alerts to 15 | - ping_status: the status of the website 16 | - ping_status_code: the status code of the website 17 | - last_ping_time: the last time the website was pinged 18 | - email_alerts_enabled: if email alerts are enabled 19 | """ 20 | __tablename__ = 'monitored_websites' 21 | 22 | id = db.Column(db.Integer, primary_key=True) 23 | name = db.Column(db.String(255), nullable=False) 24 | ping_interval = db.Column(db.Integer, nullable=False) # in seconds 25 | is_ping_active = db.Column(db.Boolean, default=True) # True: ping the site, False: do not ping 26 | email_alerts_enabled = db.Column(db.Boolean, default=False) 27 | email_address = db.Column(db.String(255), nullable=True) 28 | ping_status = db.Column(db.String(50), nullable=True) # Stores 'UP' or 'DOWN' 29 | ping_status_code = db.Column(db.Integer, nullable=True) 30 | last_ping_time = db.Column(db.DateTime, nullable=True) 31 | 32 | 33 | def __repr__(self): 34 | return f'' -------------------------------------------------------------------------------- /src/models/network_speed_test_result.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from src.config import db 4 | from src.models.base_model import BaseModel 5 | 6 | 7 | class NetworkSpeedTestResult(BaseModel): 8 | """ 9 | Network speed test result model for the application 10 | --- 11 | Properties: 12 | - id: int 13 | - download_speed: the download speed 14 | - upload_speed: the upload speed 15 | - ping: the ping 16 | - timestamp: the timestamp of the speed test 17 | """ 18 | __tablename__ = "network_speed_test_result" 19 | id = db.Column(db.Integer, primary_key=True) 20 | download_speed = db.Column(db.String(50)) 21 | upload_speed = db.Column(db.String(50)) 22 | ping = db.Column(db.String(50)) 23 | timestamp = db.Column(db.DateTime, default=datetime.datetime.now()) 24 | 25 | def __repr__(self): 26 | return ( 27 | f"" 28 | ) 29 | -------------------------------------------------------------------------------- /src/models/page_toggle_settings.py: -------------------------------------------------------------------------------- 1 | from src.config import db 2 | from src.models.base_model import BaseModel 3 | 4 | 5 | class PageToggleSettings(BaseModel): 6 | """ 7 | Page toggle settings model for the application 8 | --- 9 | Properties: 10 | - id: int 11 | - user_id: the user id 12 | - is_cpu_info_enabled: if CPU info is enabled 13 | - is_memory_info_enabled: if memory info is enabled 14 | - is_disk_info_enabled: if disk info is enabled 15 | - is_network_info_enabled: if network info is enabled 16 | - is_process_info_enabled: if process info is enabled 17 | - is_dashboard_network_enabled: if the dashboard network is enabled 18 | """ 19 | __tablename__ = 'feature_toggle_settings' 20 | 21 | id = db.Column(db.Integer, primary_key=True) 22 | user_id = db.Column(db.Integer, db.ForeignKey('users.id')) 23 | 24 | # Feature Toggles 25 | is_cpu_info_enabled = db.Column(db.Boolean, default=True) 26 | is_memory_info_enabled = db.Column(db.Boolean, default=True) 27 | is_disk_info_enabled = db.Column(db.Boolean, default=True) 28 | is_network_info_enabled = db.Column(db.Boolean, default=True) 29 | is_process_info_enabled = db.Column(db.Boolean, default=True) 30 | is_dashboard_network_enabled = db.Column(db.Boolean, default=True) 31 | 32 | @classmethod 33 | def get_feature_toggle_settings(cls, user_id): 34 | """ 35 | Get the feature toggle settings for the user 36 | """ 37 | return cls.query.filter_by(user_id=user_id).first() 38 | 39 | @classmethod 40 | def update_feature_toggle_settings(cls, user_id, **kwargs): 41 | """ 42 | Update the feature toggle settings for the user 43 | """ 44 | feature_toggle_settings = cls.get_feature_toggle_settings(user_id) 45 | if feature_toggle_settings: 46 | feature_toggle_settings.update(**kwargs) 47 | db.session.commit() 48 | else: 49 | feature_toggle_settings = cls(user_id=user_id, **kwargs) 50 | db.session.add(feature_toggle_settings) 51 | db.session.commit() 52 | return feature_toggle_settings 53 | -------------------------------------------------------------------------------- /src/models/prometheus_model.py: -------------------------------------------------------------------------------- 1 | from src.config import db 2 | from src.models.base_model import BaseModel 3 | 4 | 5 | class ExternalMonitornig(BaseModel): 6 | id = db.Column(db.Integer, primary_key=True) 7 | file_path = db.Column(db.String(100), nullable=False) 8 | is_active = db.Column(db.Boolean, default=True) 9 | -------------------------------------------------------------------------------- /src/models/smtp_configuration.py: -------------------------------------------------------------------------------- 1 | from src.config import db 2 | from src.models.base_model import BaseModel 3 | 4 | 5 | class SMTPSettings(BaseModel): 6 | """ 7 | SMTP settings model for the application 8 | --- 9 | Properties: 10 | - id: int 11 | - username: the username for the SMTP server 12 | - password: the password for the SMTP server 13 | - smtp_server: the SMTP server 14 | - smtp_port: the SMTP port 15 | - email_from: the email address to send from 16 | """ 17 | __tablename__ = "smtp_settings" 18 | id = db.Column(db.Integer, primary_key=True) 19 | username = db.Column(db.String(150), unique=True, nullable=False) 20 | password = db.Column(db.String(150), nullable=False) 21 | smtp_server = db.Column(db.String(150), nullable=False) 22 | smtp_port = db.Column(db.Integer, nullable=False) 23 | email_from = db.Column(db.String(150), nullable=False) 24 | 25 | def __repr__(self): 26 | return f"" 27 | 28 | def to_dict(self): 29 | return { 30 | "id": self.id, 31 | "username": self.username, 32 | "smtp_server": self.smtp_server, 33 | "smtp_port": self.smtp_port, 34 | "email_from": self.email_from 35 | } 36 | 37 | def save(self): 38 | db.session.add(self) 39 | db.session.commit() 40 | 41 | def delete(self): 42 | db.session.delete(self) 43 | db.session.commit() 44 | 45 | @staticmethod 46 | def get_all(): 47 | return SMTPSettings.query.all() 48 | 49 | @staticmethod 50 | def get_by_id(id): 51 | return SMTPSettings.query.get(id) 52 | 53 | @staticmethod 54 | def get_by_username(username): 55 | return SMTPSettings.query.filter_by(username=username).first() 56 | -------------------------------------------------------------------------------- /src/models/system_information.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from src.config import db 4 | from src.models.base_model import BaseModel 5 | 6 | 7 | class SystemInformation(BaseModel): 8 | """ 9 | System information model for the application 10 | --- 11 | Properties: 12 | - id: int 13 | - cpu_percent: the CPU percentage 14 | - memory_percent: the memory percentage 15 | - battery_percent: the battery percentage 16 | - network_sent: the network sent 17 | - network_received: the network received 18 | - timestamp: the timestamp of the system information 19 | """ 20 | __tablename__ = "system_information" 21 | id = db.Column(db.Integer, primary_key=True) 22 | cpu_percent = db.Column(db.Float, nullable=False) 23 | memory_percent = db.Column(db.Float, nullable=False) 24 | battery_percent = db.Column(db.Float, nullable=False) 25 | network_sent = db.Column(db.Float, nullable=False) 26 | network_received = db.Column(db.Float, nullable=False) 27 | dashboard_memory_usage = db.Column(db.Float, nullable=False) 28 | cpu_frequency = db.Column(db.Float, nullable=False) 29 | current_temp = db.Column(db.Float, nullable=False) 30 | timestamp = db.Column(db.DateTime, nullable=False) 31 | -------------------------------------------------------------------------------- /src/models/user_card_settings.py: -------------------------------------------------------------------------------- 1 | from src.config import db 2 | from src.models.base_model import BaseModel 3 | 4 | class UserCardSettings(BaseModel): 5 | """ 6 | User card settings model for the application 7 | --- 8 | Properties: 9 | - id: int 10 | - user_id: the user id 11 | - is_user_card_enabled: if the user card is enabled 12 | - is_server_card_enabled: if the server card is enabled 13 | - is_battery_card_enabled: if the battery card is enabled 14 | - is_cpu_core_card_enabled: if the CPU core card is enabled 15 | - is_cpu_usage_card_enabled: if the CPU usage card is enabled 16 | - is_cpu_temp_card_enabled: if the CPU temp card is enabled 17 | - is_dashboard_memory_card_enabled: if the dashboard memory card is enabled 18 | - is_memory_usage_card_enabled: if the memory usage card is enabled 19 | - is_disk_usage_card_enabled: if the disk usage card is enabled 20 | - is_system_uptime_card_enabled: if the system uptime card is enabled 21 | - is_network_statistic_card_enabled: if the network statistic card is enabled 22 | - is_speedtest_enabled: if speedtests are enabled 23 | """ 24 | __tablename__ = "user_card_settings" 25 | 26 | id = db.Column(db.Integer, primary_key=True) 27 | user_id = db.Column(db.Integer, db.ForeignKey("users.id")) 28 | 29 | # Card Toggles 30 | is_user_card_enabled = db.Column(db.Boolean, default=True) 31 | is_server_card_enabled = db.Column(db.Boolean, default=True) 32 | is_battery_card_enabled = db.Column(db.Boolean, default=True) 33 | is_cpu_core_card_enabled = db.Column(db.Boolean, default=True) 34 | is_cpu_usage_card_enabled = db.Column(db.Boolean, default=True) 35 | is_cpu_temp_card_enabled = db.Column(db.Boolean, default=True) 36 | is_dashboard_memory_card_enabled = db.Column(db.Boolean, default=True) 37 | is_memory_usage_card_enabled = db.Column(db.Boolean, default=True) 38 | is_disk_usage_card_enabled = db.Column(db.Boolean, default=True) 39 | is_system_uptime_card_enabled = db.Column(db.Boolean, default=True) 40 | is_network_statistic_card_enabled = db.Column(db.Boolean, default=True) 41 | is_speedtest_enabled = db.Column(db.Boolean, default=True) 42 | -------------------------------------------------------------------------------- /src/models/user_dashboard_settings.py: -------------------------------------------------------------------------------- 1 | 2 | from src.config import db 3 | from src.models.base_model import BaseModel 4 | 5 | 6 | class UserDashboardSettings(BaseModel): 7 | """ 8 | User dashboard settings model for the application 9 | --- 10 | Properties: 11 | - id: int 12 | - user_id: the user id 13 | - speedtest_cooldown: the cooldown for speedtests 14 | - number_of_speedtests: the number of speedtests 15 | - refresh_interval: the refresh interval for the dashboard 16 | """ 17 | __tablename__ = 'user_dashboard_settings' 18 | 19 | id = db.Column(db.Integer, primary_key=True) 20 | user_id = db.Column(db.Integer, db.ForeignKey('users.id')) 21 | speedtest_cooldown = db.Column(db.Integer, default=30) 22 | number_of_speedtests = db.Column(db.Integer, default=3) 23 | refresh_interval = db.Column(db.Integer, default=5) 24 | bytes_to_megabytes = db.Column(db.Integer, default=1000) 25 | 26 | -------------------------------------------------------------------------------- /src/routes/__init__.py: -------------------------------------------------------------------------------- 1 | from src.routes.cpu_info import cpu_info_bp 2 | from src.routes.disk_info import disk_info_bp 3 | from src.routes.dashboard import dashboard_bp 4 | from src.routes.memory_info import memory_info_bp 5 | from src.routes.network_info import network_info_bp 6 | from src.routes.settings import settings_bp 7 | from src.routes.speedtest import speedtest_bp 8 | from src.routes.process_info import process_bp 9 | from src.routes.auth import auth_bp 10 | from src.routes.dashboard_network import network_bp 11 | from src.routes.other import other_bp 12 | from src.routes.smtp_email_config import smtp_email_config_bp 13 | from src.routes.user_management import user_management_bp 14 | from src.routes.graphs import graphs_bp 15 | from src.routes.ping import ping_bp 16 | from src.routes.firewall import firewall_bp 17 | from src.routes.health import health_bp 18 | from src.routes.api import api_bp 19 | from src.routes.experimental import experimental_bp 20 | from src.routes.error_handlers import error_handlers_bp 21 | from src.routes.profile import profile_bp 22 | from src.routes.prometheus import prometheus_bp 23 | from src.routes.alert_route import alert_bp 24 | from src.routes.update_webhooks import webhooks_bp 25 | 26 | __all__ = [ 27 | "cpu_info_bp", 28 | "disk_info_bp", 29 | "dashboard_bp", 30 | "memory_info_bp", 31 | "network_info_bp", 32 | "settings_bp", 33 | "speedtest_bp", 34 | "process_bp", 35 | "auth_bp", 36 | "network_bp", 37 | "other_bp", 38 | "smtp_email_config_bp", 39 | "user_management_bp", 40 | "graphs_bp", 41 | "ping_bp", 42 | "firewall_bp", 43 | "health_bp", 44 | "api_bp", 45 | "experimental_bp", 46 | "error_handlers_bp", 47 | "profile_bp", 48 | "prometheus_bp", 49 | "alert_bp", 50 | "webhooks_bp", 51 | ] -------------------------------------------------------------------------------- /src/routes/cpu_info.py: -------------------------------------------------------------------------------- 1 | from flask import render_template, blueprints 2 | 3 | from flask_login import login_required 4 | 5 | from src.config import app 6 | from src.utils import get_cpu_core_count, get_cpu_frequency, cpu_usage_percent, get_cpu_temp, get_cached_value 7 | from src.routes.helper.common_helper import check_page_toggle 8 | cpu_info_bp = blueprints.Blueprint("cpu_usage", __name__) 9 | 10 | @app.route("/cpu_usage") 11 | @login_required 12 | @check_page_toggle("is_cpu_info_enabled") 13 | def cpu_usage(): 14 | 15 | current_temp, high_temp, critical_temp = get_cpu_temp() 16 | cpu_core = get_cached_value("cpu_core", get_cpu_core_count) 17 | cpu_frequency, cpu_max_frequency = get_cpu_frequency() 18 | system_info = { 19 | "cpu_core": cpu_core, 20 | "cpu_frequency": cpu_frequency, 21 | "cpu_max_frequency": cpu_max_frequency, 22 | "cpu_percent": cpu_usage_percent(), 23 | "current_temp": current_temp, 24 | "high_temp": high_temp, 25 | "critical_temp": critical_temp, 26 | } 27 | 28 | return render_template("info_pages/cpu_info.html", system_info=system_info) 29 | -------------------------------------------------------------------------------- /src/routes/dashboard_network.py: -------------------------------------------------------------------------------- 1 | from flask import render_template, blueprints 2 | 3 | from src.config import app 4 | from src.routes.helper.common_helper import admin_required 5 | 6 | network_bp = blueprints.Blueprint('network', __name__) 7 | 8 | @app.route('/dashboard_network', methods=['GET']) 9 | @admin_required 10 | def dashboard_network(): 11 | return render_template('network/dashboard_network.html') 12 | -------------------------------------------------------------------------------- /src/routes/disk_info.py: -------------------------------------------------------------------------------- 1 | import psutil 2 | 3 | from flask import render_template, blueprints 4 | from flask_login import login_required 5 | from src.config import app 6 | from src.utils import get_cached_value, get_disk_free, get_disk_total, get_disk_used, get_disk_usage_percent 7 | from src.routes.helper.common_helper import check_page_toggle 8 | disk_info_bp = blueprints.Blueprint("disk_usage", __name__) 9 | 10 | @app.route("/disk_usage") 11 | @login_required 12 | @check_page_toggle("is_disk_info_enabled") 13 | def disk_usage(): 14 | 15 | disk_total = get_cached_value("disk_total", get_disk_total) 16 | system_info = { 17 | "disk_percent": get_disk_usage_percent(), 18 | "disk_total": disk_total, 19 | "disk_used": get_disk_used(), 20 | "disk_free": get_disk_free(), 21 | } 22 | return render_template("info_pages/disk_info.html", system_info=system_info) 23 | 24 | -------------------------------------------------------------------------------- /src/routes/experimental.py: -------------------------------------------------------------------------------- 1 | from flask import render_template, request, blueprints 2 | 3 | from src.config import app 4 | from src.routes.helper.network_helper import handle_network_scan, handle_port_scan 5 | 6 | experimental_bp = blueprints.Blueprint('experimental', __name__) 7 | 8 | @app.route('/security_analysis', methods=['GET', 'POST']) 9 | def security_analysis(): 10 | if request.method == 'POST': 11 | if 'scan_network' in request.form: 12 | return handle_network_scan() 13 | elif 'scan_ports' in request.form: 14 | return handle_port_scan() 15 | 16 | # Render the default scan page if the request method is GET or no valid action is found in POST. 17 | return render_template('experimental/scan.html') 18 | 19 | -------------------------------------------------------------------------------- /src/routes/graphs.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | from flask import render_template, blueprints 3 | from src.config import app 4 | from src.routes.helper.common_helper import admin_required 5 | 6 | graphs_bp = blueprints.Blueprint("graphs", __name__) 7 | 8 | @app.route('/historical_system_metrics') 9 | @admin_required 10 | def historical_system_metrics(): 11 | return render_template('graphs/historical_system_metrics.html') 12 | 13 | 14 | @app.route('/historical_alerts_metrics') 15 | @admin_required 16 | def historical_alerts_metrics(): 17 | return render_template('graphs/historical_alerts_metrics.html') 18 | 19 | # bar graph 20 | # Compare the number of alerts across different instances and severity levels. 21 | # multi bar based on severity 22 | 23 | # Pie Chart 24 | # Purpose: Show the proportion of different severity levels across all instances. 25 | 26 | -------------------------------------------------------------------------------- /src/routes/health.py: -------------------------------------------------------------------------------- 1 | from flask import jsonify, blueprints 2 | from src.config import app 3 | 4 | health_bp = blueprints.Blueprint("health", __name__) 5 | 6 | # health page 7 | @app.route("/health", methods=["GET"]) 8 | def health(): 9 | return jsonify({"status": "ok"}) 10 | 11 | -------------------------------------------------------------------------------- /src/routes/helper/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/src/routes/helper/__init__.py -------------------------------------------------------------------------------- /src/routes/helper/unique_id_helper.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | import functools 4 | 5 | number_of_sum_check_digits = 5 6 | 7 | def calculate_checksum(unique_id, num_of_digits=2): 8 | """Calculate a simple checksum for the given unique ID.""" 9 | checksum = sum((index + 1) * ord(char) for index, char in enumerate(unique_id)) 10 | return checksum % (10 ** num_of_digits) 11 | 12 | def get_os_installation_uuid(): 13 | """Retrieve the OS installation UUID.""" 14 | try: 15 | if os.path.exists('/etc/machine-id'): 16 | with open('/etc/machine-id', 'r') as f: 17 | return f.read().strip() 18 | elif os.path.exists('/var/lib/dbus/machine-id'): 19 | with open('/var/lib/dbus/machine-id', 'r') as f: 20 | return f.read().strip() 21 | else: 22 | return "OS Installation UUID not found." 23 | except Exception as e: 24 | return f"Error reading OS Installation UUID: {str(e)}" 25 | 26 | def get_motherboard_serial(sudo_password): 27 | """Retrieve the motherboard serial number using sudo password.""" 28 | try: 29 | command = f"echo {sudo_password} | sudo -S dmidecode -s baseboard-serial-number" 30 | output = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT) 31 | return output.decode().strip() 32 | except subprocess.CalledProcessError as e: 33 | return "Error retrieving Motherboard Serial: " + e.output.decode().strip() 34 | except Exception as e: 35 | return f"Unexpected error: {str(e)}" 36 | 37 | @functools.lru_cache(maxsize=1) 38 | def calculate_unique_system_id(sudo_password): 39 | """Calculate a unique system identifier using various hardware IDs.""" 40 | os_uuid = get_os_installation_uuid() 41 | motherboard_serial = get_motherboard_serial(sudo_password) 42 | unique_id = f"{os_uuid}:{motherboard_serial}" 43 | unique_id = ''.join(e for e in unique_id if e.isalnum()) 44 | checksum = calculate_checksum(unique_id, number_of_sum_check_digits) 45 | unique_id += f"{checksum}" 46 | return unique_id 47 | -------------------------------------------------------------------------------- /src/routes/memory_info.py: -------------------------------------------------------------------------------- 1 | from flask import render_template, blueprints 2 | from flask_login import login_required 3 | 4 | from src.config import app 5 | from src.utils import get_cached_value, get_memory_percent, get_memory_available, get_memory_used, get_swap_memory_info, get_flask_memory_usage 6 | from src.routes.helper.common_helper import check_page_toggle 7 | 8 | memory_info_bp = blueprints.Blueprint("memory_usage", __name__) 9 | 10 | 11 | @app.route("/memory_usage") 12 | @login_required 13 | @check_page_toggle("is_memory_info_enabled") 14 | def memory_usage(): 15 | memory_available = get_cached_value("memory_available", get_memory_available) 16 | system_info = { 17 | "memory_percent": get_memory_percent(), 18 | "memory_available": memory_available, 19 | "memory_used": get_memory_used(), 20 | 'dashboard_memory_usage': get_flask_memory_usage(), 21 | } 22 | 23 | swap_info = get_swap_memory_info() 24 | system_info.update(swap_info) 25 | 26 | return render_template("info_pages/memory_info.html", system_info=system_info) 27 | -------------------------------------------------------------------------------- /src/routes/network_info.py: -------------------------------------------------------------------------------- 1 | from flask import render_template, blueprints, render_template 2 | from flask_login import login_required 3 | from src.config import app 4 | from src.utils import get_established_connections, get_ip_address, get_network_io 5 | from src.routes.helper.common_helper import check_page_toggle 6 | 7 | network_info_bp = blueprints.Blueprint("network_stats", __name__) 8 | 9 | 10 | @app.route("/network_stats") 11 | @login_required 12 | @check_page_toggle("is_network_info_enabled") 13 | def network_stats(): 14 | 15 | network_sent, network_received = get_network_io() 16 | _, ipv6_ip = get_established_connections() 17 | ipv4_ip = get_ip_address() 18 | 19 | system_info = { 20 | "network_sent": network_sent, 21 | "network_received": network_received, 22 | "ipv4_ip": ipv4_ip, 23 | "ipv6_ip": ipv6_ip, 24 | } 25 | 26 | return render_template("info_pages/network_info.html", system_info=system_info) 27 | 28 | -------------------------------------------------------------------------------- /src/routes/smtp_email_config.py: -------------------------------------------------------------------------------- 1 | from flask import render_template, request, flash, redirect, url_for, blueprints 2 | 3 | from src.config import app, db 4 | from src.models import SMTPSettings 5 | from src.routes.helper.common_helper import admin_required 6 | 7 | smtp_email_config_bp = blueprints.Blueprint('smtp_email_config', __name__) 8 | 9 | 10 | @app.route("/update-email-password", methods=["GET", "POST"]) 11 | @admin_required 12 | def smtp_config(): 13 | smtp_config = SMTPSettings.query.first() 14 | 15 | if request.method == "POST": 16 | username = request.form.get("username") 17 | new_password = request.form.get("password") 18 | smtp_server = request.form.get("smtp_server") 19 | smtp_port = request.form.get("smtp_port") 20 | email_from = request.form.get("email_from") 21 | 22 | 23 | if not username or not new_password: 24 | flash("Please provide email and password.", "danger") 25 | return redirect(url_for("smtp_config")) 26 | 27 | 28 | if not smtp_config: 29 | smtp_config = SMTPSettings(username=username, password=new_password, 30 | smtp_server=smtp_server, smtp_port=smtp_port, 31 | email_from=email_from) 32 | db.session.add(smtp_config) 33 | else: 34 | smtp_config.username = username 35 | smtp_config.password = new_password 36 | 37 | db.session.commit() 38 | flash("Email and password updated successfully!", "success") 39 | return redirect(url_for("smtp_config")) 40 | 41 | return render_template("other/smtp_config.html", smtp_config=smtp_config) 42 | -------------------------------------------------------------------------------- /src/scripts/initialization/init_alertmanager.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Set the path for the Alertmanager configuration file 4 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 5 | PROMETHEUS_CONFIG_DIR="$(dirname "$(dirname "$(dirname "$SCRIPT_DIR")")")/prometheus_config" 6 | ALERTMANAGER_CONFIG_FILE="$PROMETHEUS_CONFIG_DIR/alertmanager.yml" 7 | IP_ADDRESS=$(hostname -I | awk '{print $1}') 8 | 9 | # Create the Alertmanager configuration 10 | cat > "$ALERTMANAGER_CONFIG_FILE" </dev/null) # Redirect any error output to /dev/null 7 | if [ $? -ne 0 ]; then # Check if the exit status of the last command is not 0 8 | USER_NAME=$(cat /etc/passwd | grep '/home' | cut -d: -f1 | tail -n 1) 9 | else 10 | USER_NAME=$LOGNAME_USER 11 | fi 12 | else 13 | USER_NAME=$(whoami) 14 | fi 15 | echo "$USER_NAME" 16 | } 17 | 18 | USER_NAME=$(get_user_name) 19 | # Configuration 20 | CURRENT_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" 21 | CURRENT_DIR="$CURRENT_SCRIPT_DIR" 22 | ROOT_DIR="$(dirname "$(dirname "$CURRENT_DIR")")" 23 | PROMETHEUS_CONFIG_DIR="$ROOT_DIR/prometheus_config" 24 | CONTAINER_NAME="prometheus" 25 | PROMETHEUS_CONFIG="$PROMETHEUS_CONFIG_DIR/prometheus.yml" 26 | PROMETHEUS_DATA_DIR="/home/$USER_NAME/.database/prometheus" 27 | PROMETHEUS_IMAGE="prom/prometheus" # Add your image name if needed 28 | NETWORK_NAME="flask-prometheus-net" # Specify your network name 29 | PROMETHEUS_PORT="9090" # Specify your port 30 | 31 | # Logging function for better readability 32 | log() { 33 | echo "[INFO] $1" 34 | } 35 | 36 | # Check if Prometheus container is running 37 | if [ "$(docker ps -q -f name="$CONTAINER_NAME")" ]; then 38 | log "Stopping container: $CONTAINER_NAME" 39 | docker stop "$CONTAINER_NAME" 40 | 41 | log "Starting container: $CONTAINER_NAME with new configuration" 42 | docker start "$CONTAINER_NAME" 43 | 44 | log "Reloading configuration for container: $CONTAINER_NAME" 45 | docker exec "$CONTAINER_NAME" kill -HUP 1 # Send SIGHUP to reload config 46 | else 47 | log "Container $CONTAINER_NAME is not running. Starting a new container." 48 | docker run -d \ 49 | --name "$CONTAINER_NAME" \ 50 | --network "$NETWORK_NAME" \ 51 | -p "$PROMETHEUS_PORT:$PROMETHEUS_PORT" \ 52 | --restart always \ 53 | -v "$PROMETHEUS_CONFIG:/etc/prometheus/prometheus.yml" \ 54 | -v "$PROMETHEUS_DATA_DIR:/prometheus" \ 55 | "$PROMETHEUS_IMAGE" &> /dev/null 56 | 57 | log "Prometheus container started successfully." 58 | fi 59 | 60 | log "Prometheus container has been updated with the new configuration." 61 | -------------------------------------------------------------------------------- /src/scripts/utils/cpu_stress.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import time 3 | import multiprocessing 4 | 5 | # Function to consume CPU 6 | def cpu_stress(duration): 7 | # Get the start time 8 | end_time = time.time() + duration 9 | while time.time() < end_time: 10 | # Simulate some CPU-heavy operation 11 | x = 0 12 | for _ in range(1000000): 13 | x += 1 14 | 15 | def start_cpu_stress(duration, num_threads=None): 16 | if num_threads is None: 17 | # Default to the number of CPU cores if num_threads is not provided 18 | num_threads = multiprocessing.cpu_count() 19 | 20 | print(f"Starting CPU stress test with {num_threads} threads for {duration} seconds...") 21 | 22 | # Create and start threads 23 | threads = [] 24 | for _ in range(num_threads): 25 | thread = threading.Thread(target=cpu_stress, args=(duration,)) 26 | threads.append(thread) 27 | thread.start() 28 | 29 | # Wait for all threads to finish 30 | for thread in threads: 31 | thread.join() 32 | 33 | print("CPU stress test completed.") 34 | 35 | if __name__ == "__main__": 36 | # Set duration and number of threads (CPU cores) for the stress test 37 | duration = 30 # Duration in seconds 38 | num_threads = multiprocessing.cpu_count() # Number of threads equal to CPU cores 39 | 40 | # Start the CPU stress test 41 | start_cpu_stress(duration, num_threads) 42 | -------------------------------------------------------------------------------- /src/scripts/utils/line_counter.py: -------------------------------------------------------------------------------- 1 | import os 2 | from collections import defaultdict 3 | 4 | # Define the root directory of your project 5 | root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../..')) 6 | 7 | # Function to count lines in a file 8 | def count_lines_in_file(file_path): 9 | with open(file_path, 'r', encoding='utf-8', errors='ignore') as file: 10 | return sum(1 for _ in file) 11 | 12 | # Function to categorize extensions into file types 13 | def categorize_extension(ext): 14 | if ext in ['.py']: 15 | return 'Python' 16 | elif ext in ['.html', '.htm']: 17 | return 'HTML' 18 | elif ext in ['.sh']: 19 | return 'Shell' 20 | elif ext in ['.js']: 21 | return 'JavaScript' 22 | elif ext in ['.css']: 23 | return 'CSS' 24 | else: 25 | return None # Exclude 'Other' 26 | 27 | # Initialize a dictionary to store line counts by file type 28 | line_counts = defaultdict(int) 29 | 30 | # Walk through the directory and count lines for each categorized file type 31 | for dirpath, _, filenames in os.walk(root_dir): 32 | for filename in filenames: 33 | file_ext = os.path.splitext(filename)[1].lower() # Get file extension 34 | file_type = categorize_extension(file_ext) 35 | if file_type: # Only process known file types 36 | file_path = os.path.join(dirpath, filename) 37 | line_counts[file_type] += count_lines_in_file(file_path) 38 | 39 | # Calculate total lines for percentage calculation 40 | total_lines = sum(line_counts.values()) 41 | 42 | # Sort line counts by percentage in descending order 43 | sorted_line_counts = sorted(line_counts.items(), key=lambda x: (x[1] / total_lines) if total_lines > 0 else 0, reverse=True) 44 | 45 | print("## Line Counts by File Type", end='\n\n') 46 | # Print the results in a Markdown table format with percentages 47 | print("| File Type | Number of Lines | Percentage |") 48 | print("|-------------|-----------------|------------|") 49 | for file_type, count in sorted_line_counts: 50 | percentage = (count / total_lines) * 100 if total_lines > 0 else 0 51 | print(f"| {file_type:<11} | {count:<15} | {percentage:>9.2f}% |") 52 | 53 | # Print the total line count 54 | print(f"| **Total** | {total_lines:<15} | {'100.00%':>9} |") 55 | -------------------------------------------------------------------------------- /src/scripts/utils/locustfile.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from locust import HttpUser, TaskSet, task, between 4 | from locust.exception import StopUser 5 | 6 | from src.logger import logger 7 | 8 | 9 | class UserBehavior(TaskSet): 10 | 11 | def on_start(self): 12 | """ Called when a Locust user starts running """ 13 | self.login() 14 | 15 | def login(self): 16 | """ Simulate a user logging in """ 17 | response = self.client.post("/login", { 18 | "username": "admin", 19 | "password": "adminpassword" 20 | }) 21 | if response.status_code == 200 and "Invalid username or password" not in response.text: 22 | logger.info("Login successful") 23 | else: 24 | logger.info("Login failed") 25 | raise StopUser("Login failed") 26 | 27 | @task(1) 28 | def view_dashboard(self): 29 | """ Simulate viewing the dashboard """ 30 | self.client.get("/") 31 | 32 | @task(2) 33 | def view_cpu_usage(self): 34 | """ Simulate viewing CPU usage """ 35 | self.client.get("/cpu_usage") 36 | 37 | @task(1) 38 | def view_disk_usage(self): 39 | """ Simulate viewing disk usage """ 40 | self.client.get("/disk_usage") 41 | 42 | @task(1) 43 | def view_memory_usage(self): 44 | """ Simulate viewing memory usage """ 45 | self.client.get("/memory_usage") 46 | 47 | class WebsiteUser(HttpUser): 48 | tasks = [UserBehavior] 49 | wait_time = between(1, 5) # Time to wait between tasks 50 | 51 | if __name__ == "__main__": 52 | os.system("locust -f locustfile.py --host=http://localhost:5000") 53 | -------------------------------------------------------------------------------- /src/scripts/utils/minify.py: -------------------------------------------------------------------------------- 1 | import os 2 | import htmlmin 3 | 4 | def minify_html_file(file_path): 5 | # Read the original HTML file 6 | with open(file_path, 'r', encoding='utf-8') as file: 7 | html_content = file.read() 8 | 9 | # Minify the HTML content 10 | minified_content = htmlmin.minify(html_content, remove_comments=True, remove_empty_space=True) 11 | 12 | # Write the minified content back to the file 13 | with open(file_path, 'w', encoding='utf-8') as file: 14 | file.write(minified_content) 15 | print(f"Minified: {file_path}") 16 | 17 | def find_and_minify_html_files(root_directory): 18 | # Walk through all directories and files 19 | for root, _, files in os.walk(root_directory): 20 | for file in files: 21 | if file.endswith('.html'): 22 | file_path = os.path.join(root, file) 23 | minify_html_file(file_path) 24 | 25 | if __name__ == "__main__": 26 | # Get the current directory 27 | current_directory = os.getcwd() 28 | # Find and minify all HTML files 29 | find_and_minify_html_files(current_directory) 30 | -------------------------------------------------------------------------------- /src/scripts/utils/missing_dependency.py: -------------------------------------------------------------------------------- 1 | # check_requirements.py 2 | 3 | import pkg_resources 4 | import sys 5 | 6 | def get_installed_packages(): 7 | return {pkg.key for pkg in pkg_resources.working_set} 8 | 9 | def read_requirements(file_path): 10 | with open(file_path, 'r') as f: 11 | return {line.strip().split('==')[0].lower() for line in f if line.strip() and not line.startswith('#')} 12 | 13 | def main(requirements_file): 14 | installed_packages = get_installed_packages() 15 | required_packages = read_requirements(requirements_file) 16 | missing_packages = required_packages - installed_packages 17 | 18 | if missing_packages: 19 | print('\n'.join(missing_packages)) 20 | else: 21 | print('All packages are installed.') 22 | 23 | if __name__ == "__main__": 24 | if len(sys.argv) != 2: 25 | print("Usage: python check_requirements.py ") 26 | sys.exit(1) 27 | 28 | requirements_file = sys.argv[1] 29 | main(requirements_file) 30 | -------------------------------------------------------------------------------- /src/static/css/403.css: -------------------------------------------------------------------------------- 1 | .permission-denied-container { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | min-height: 80vh; 6 | background-color: #f8f9fa; 7 | } 8 | 9 | .content-wrapper { 10 | text-align: center; 11 | background-color: #ffffff; 12 | padding: 40px 60px; 13 | border-radius: 10px; 14 | box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); 15 | animation: fadeIn 0.5s ease-in-out; 16 | } 17 | 18 | .icon { 19 | font-size: 60px; 20 | color: #dc3545; 21 | margin-bottom: 20px; 22 | } 23 | 24 | h1 { 25 | font-size: 48px; 26 | margin: 10px 0; 27 | color: #dc3545; 28 | font-weight: bold; 29 | } 30 | 31 | p { 32 | font-size: 18px; 33 | margin: 20px 0; 34 | color: #6c757d; 35 | } 36 | 37 | .btn { 38 | display: inline-block; 39 | padding: 12px 24px; 40 | font-size: 16px; 41 | color: #ffffff; 42 | background-color: #007bff; 43 | border: none; 44 | border-radius: 5px; 45 | text-decoration: none; 46 | transition: background-color 0.3s ease, transform 0.3s ease; 47 | box-shadow: 0 2px 6px rgba(0, 123, 255, 0.5); 48 | } 49 | 50 | .btn:hover { 51 | background-color: #0056b3; 52 | transform: translateY(-2px); 53 | box-shadow: 0 4px 8px rgba(0, 91, 187, 0.5); 54 | } 55 | 56 | @keyframes fadeIn { 57 | from { 58 | opacity: 0; 59 | transform: translateY(-10px); 60 | } 61 | to { 62 | opacity: 1; 63 | transform: translateY(0); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/static/css/404.css: -------------------------------------------------------------------------------- 1 | .not-found-container { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | min-height: 80vh; 6 | background-color: #f8f9fa; 7 | } 8 | 9 | .content-wrapper { 10 | text-align: center; 11 | background-color: #ffffff; 12 | padding: 50px 70px; 13 | border-radius: 12px; 14 | box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); 15 | animation: fadeIn 0.5s ease-in-out; 16 | } 17 | 18 | .icon { 19 | font-size: 80px; 20 | color: #ffc107; 21 | margin-bottom: 20px; 22 | } 23 | 24 | h1 { 25 | font-size: 80px; 26 | margin: 10px 0; 27 | color: #dc3545; 28 | font-weight: bold; 29 | } 30 | 31 | p { 32 | font-size: 18px; 33 | margin: 15px 0 30px; 34 | color: #6c757d; 35 | } 36 | 37 | .btn { 38 | display: inline-block; 39 | padding: 12px 24px; 40 | font-size: 16px; 41 | color: #ffffff; 42 | background-color: #007bff; 43 | border: none; 44 | border-radius: 5px; 45 | text-decoration: none; 46 | transition: background-color 0.3s ease, transform 0.3s ease; 47 | box-shadow: 0 2px 6px rgba(0, 123, 255, 0.5); 48 | } 49 | 50 | .btn:hover { 51 | background-color: #0056b3; 52 | transform: translateY(-2px); 53 | box-shadow: 0 4px 8px rgba(0, 91, 187, 0.5); 54 | } 55 | 56 | @keyframes fadeIn { 57 | from { 58 | opacity: 0; 59 | transform: translateY(-10px); 60 | } 61 | to { 62 | opacity: 1; 63 | transform: translateY(0); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/static/css/active_alerts.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, sans-serif; 3 | } 4 | 5 | table { 6 | width: 100%; 7 | border-collapse: collapse; 8 | } 9 | 10 | th, td { 11 | padding: 8px; 12 | text-align: left; 13 | border: 1px solid #ddd; 14 | } 15 | 16 | th { 17 | background-color: #f2f2f2; 18 | } 19 | 20 | .warning { 21 | background-color: #ffcc00; 22 | } 23 | 24 | .critical { 25 | background-color: #ff6666; 26 | } 27 | 28 | .info { 29 | background-color: #66ccff; 30 | } 31 | 32 | .test { 33 | background-color: #66ff66; 34 | } 35 | 36 | h1 { 37 | font-weight: bold; 38 | text-align: center; 39 | } -------------------------------------------------------------------------------- /src/static/css/add_server.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, sans-serif; 3 | background-color: #f4f4f4; 4 | color: #333; 5 | } 6 | 7 | .container { 8 | max-width: 600px; 9 | margin: 50px auto; 10 | padding: 30px; 11 | background-color: #fff; 12 | border-radius: 10px; 13 | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); 14 | } 15 | 16 | h1 { 17 | text-align: center; 18 | color: #333; 19 | font-size: 24px; 20 | margin-bottom: 30px; 21 | font-weight: 600; 22 | } 23 | 24 | .form-group { 25 | margin-bottom: 20px; 26 | } 27 | 28 | label { 29 | display: block; 30 | margin-bottom: 8px; 31 | font-weight: bold; 32 | color: #555; 33 | } 34 | 35 | input[type="text"], 36 | input[type="number"], 37 | textarea, 38 | select { 39 | width: 100%; 40 | padding: 12px; 41 | margin-bottom: 10px; 42 | border: 1px solid #ccc; 43 | border-radius: 6px; 44 | font-size: 14px; 45 | transition: border-color 0.3s ease; 46 | } 47 | 48 | input[type="text"]:focus, 49 | input[type="number"]:focus, 50 | textarea:focus, 51 | select:focus { 52 | border-color: #007bff; 53 | outline: none; 54 | } 55 | 56 | button { 57 | display: block; 58 | width: 100%; 59 | padding: 12px; 60 | background-color: #007bff; 61 | color: #fff; 62 | border: none; 63 | border-radius: 6px; 64 | font-size: 16px; 65 | font-weight: 600; 66 | cursor: pointer; 67 | transition: background-color 0.3s ease; 68 | } 69 | 70 | button:hover { 71 | background-color: #0056b3; 72 | } 73 | -------------------------------------------------------------------------------- /src/static/css/alert_history.css: -------------------------------------------------------------------------------- 1 | /* alert_history.css */ 2 | 3 | /* Basic resets and styles */ 4 | body { 5 | font-family: Arial, sans-serif; 6 | background-color: #f8f9fa; 7 | color: #343a40; 8 | } 9 | 10 | .container { 11 | margin: auto; 12 | max-width: 1200px; 13 | } 14 | 15 | /* Header styles */ 16 | h2 { 17 | text-align: center; 18 | margin-bottom: 20px; 19 | } 20 | 21 | .bg-danger { 22 | background-color: #dc3545 !important; 23 | } 24 | 25 | .bg-warning { 26 | background-color: #ffc107 !important; 27 | } 28 | 29 | /* Table styles */ 30 | .table { 31 | background-color: #ffffff; 32 | border-radius: 0.25rem; 33 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); 34 | } 35 | 36 | .table th, .table td { 37 | padding: 12px 15px; 38 | text-align: center; 39 | } 40 | 41 | .table th { 42 | background-color: #007bff; 43 | color: #ffffff; 44 | } 45 | 46 | .table tbody tr { 47 | transition: background-color 0.3s; 48 | } 49 | 50 | .table tbody tr:hover { 51 | background-color: #f1f1f1; 52 | } 53 | 54 | /* Font Awesome icon styles */ 55 | .icon { 56 | margin-right: 5px; 57 | } 58 | -------------------------------------------------------------------------------- /src/static/css/alertmanager_status.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, sans-serif; 3 | background-color: #f4f6f8; 4 | color: #333; 5 | } 6 | 7 | h1 { 8 | text-align: center; 9 | color: #0056b3; 10 | } 11 | 12 | .status-container { 13 | width: 80%; 14 | margin: 20px auto; 15 | padding: 20px; 16 | background-color: #fff; 17 | border-radius: 8px; 18 | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); 19 | } 20 | 21 | .alertmanager-table { 22 | width: 100%; 23 | border-collapse: collapse; 24 | margin-top: 20px; 25 | } 26 | 27 | .alertmanager-table th, .alertmanager-table td { 28 | padding: 12px; 29 | text-align: left; 30 | border-bottom: 1px solid #ddd; 31 | } 32 | 33 | .alertmanager-table th { 34 | background-color: #0056b3; 35 | color: white; 36 | } 37 | 38 | .alertmanager-table tr:hover { 39 | background-color: #f1f3f5; 40 | } 41 | 42 | .alertmanager-table td { 43 | color: #333; 44 | } 45 | -------------------------------------------------------------------------------- /src/static/css/card.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/src/static/css/card.css -------------------------------------------------------------------------------- /src/static/css/change_user.css: -------------------------------------------------------------------------------- 1 | .change-user-container { 2 | max-width: 650px; 3 | margin: 0 auto; 4 | padding: 30px; 5 | background-color: #f8f9fa; 6 | border-radius: 10px; 7 | box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1); 8 | } 9 | 10 | .page-title { 11 | font-size: 30px; 12 | text-align: center; 13 | margin-bottom: 20px; 14 | } 15 | 16 | .change-user-form { 17 | display: flex; 18 | flex-direction: column; 19 | gap: 20px; 20 | } 21 | 22 | .form-group label { 23 | font-size: 16px; 24 | color: #333; 25 | font-weight: bold; 26 | } 27 | 28 | .form-control { 29 | font-size: 16px; 30 | padding: 12px; 31 | border-radius: 6px; 32 | border: 1px solid #ced4da; 33 | } 34 | 35 | .form-check-input { 36 | margin-right: 10px; 37 | } 38 | 39 | .btn-primary { 40 | padding: 15px; 41 | font-size: 18px; 42 | font-weight: bold; 43 | background-color: #007bff; 44 | color: white; 45 | border-radius: 6px; 46 | transition: background-color 0.3s ease; 47 | } 48 | 49 | .btn-primary:hover { 50 | background-color: #0056b3; 51 | } 52 | -------------------------------------------------------------------------------- /src/static/css/create_user.css: -------------------------------------------------------------------------------- 1 | /* Container styling */ 2 | .add-user-container { 3 | padding: 40px; 4 | max-width: 650px; 5 | margin: 50px auto; 6 | background-color: #ffffff; 7 | border-radius: 12px; 8 | box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); 9 | } 10 | 11 | .page-title { 12 | margin-bottom: 30px; 13 | font-size: 26px; 14 | font-weight: 700; 15 | text-align: center; 16 | background-color: #007bff; 17 | color: white; 18 | border-radius: 8px; 19 | padding: 15px; 20 | } 21 | 22 | /* Form styling */ 23 | .user-form .form-group { 24 | margin-bottom: 20px; 25 | } 26 | 27 | label { 28 | font-size: 16px; 29 | font-weight: 500; 30 | color: #333; 31 | display: inline-block; 32 | margin-bottom: 8px; 33 | } 34 | 35 | input[type="text"], 36 | input[type="email"], 37 | input[type="password"], 38 | select { 39 | font-size: 16px; 40 | padding: 12px; 41 | border-radius: 6px; 42 | border: 1px solid #ced4da; 43 | width: 100%; 44 | box-sizing: border-box; 45 | } 46 | 47 | input[type="checkbox"] { 48 | width: 18px; 49 | height: 18px; 50 | } 51 | 52 | .user-form .form-check-input { 53 | margin-right: 8px; 54 | } 55 | 56 | .user-form button { 57 | background-color: #007bff; 58 | color: white; 59 | padding: 12px; 60 | border: none; 61 | border-radius: 6px; 62 | font-size: 16px; 63 | font-weight: 600; 64 | transition: background-color 0.3s ease; 65 | width: 100%; 66 | } 67 | 68 | .user-form button:hover { 69 | background-color: #0056b3; 70 | } 71 | 72 | .user-form button i { 73 | margin-right: 8px; 74 | } 75 | 76 | /* Responsive styling */ 77 | @media (max-width: 768px) { 78 | .add-user-container { 79 | padding: 30px; 80 | } 81 | 82 | .page-title { 83 | font-size: 22px; 84 | } 85 | 86 | input[type="text"], 87 | input[type="email"], 88 | input[type="password"], 89 | select { 90 | font-size: 14px; 91 | } 92 | 93 | .user-form button { 94 | font-size: 14px; 95 | padding: 10px; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/static/css/dashboard_network.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | h1 { 4 | text-align: center; 5 | color: #2c3e50; 6 | font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 7 | margin-bottom: 20px; 8 | } 9 | 10 | table { 11 | width: 100%; 12 | border-collapse: collapse; 13 | margin-bottom: 20px; 14 | background-color: white; 15 | } 16 | 17 | table th, table td { 18 | padding: 15px; 19 | border: 1px solid #e1e4e8; 20 | text-align: left; 21 | font-family: 'Arial', sans-serif; 22 | } 23 | 24 | table th { 25 | background-color: #007bff; 26 | color: white; 27 | font-weight: bold; 28 | text-transform: uppercase; 29 | } 30 | 31 | table tr:hover { 32 | background-color: #f1f1f1; 33 | } 34 | 35 | table td { 36 | font-size: 14px; 37 | color: #333; 38 | } 39 | 40 | table td.health-up { 41 | color: green; 42 | font-weight: bold; 43 | } 44 | 45 | table td.health-down { 46 | color: red; 47 | font-weight: bold; 48 | } 49 | 50 | .error-message { 51 | color: red; 52 | font-style: italic; 53 | text-align: center; 54 | } 55 | 56 | .text-center { 57 | text-align: center; 58 | margin-top: 30px; 59 | } 60 | 61 | .text-center h2 { 62 | color: #2c3e50; 63 | font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 64 | margin-bottom: 20px; 65 | } 66 | 67 | form input[type="text"] { 68 | padding: 10px; 69 | margin: 5px; 70 | width: 200px; 71 | border: 1px solid #ced4da; 72 | border-radius: 4px; 73 | font-size: 14px; 74 | } 75 | 76 | form input[type="submit"] { 77 | padding: 10px 20px; 78 | background-color: #28a745; 79 | color: white; 80 | border: none; 81 | border-radius: 4px; 82 | font-size: 14px; 83 | cursor: pointer; 84 | transition: background-color 0.3s ease; 85 | } 86 | 87 | form input[type="submit"]:hover { 88 | background-color: #218838; 89 | } 90 | 91 | footer { 92 | text-align: center; 93 | margin-top: 20px; 94 | color: #666; 95 | font-size: 12px; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src/static/css/edit_server.css: -------------------------------------------------------------------------------- 1 | /* Basic reset and font settings */ 2 | body { 3 | font-family: Arial, sans-serif; 4 | background-color: #f8f9fa; 5 | } 6 | 7 | /* Container styling */ 8 | .container { 9 | max-width: 800px; 10 | margin: 0 auto; 11 | } 12 | 13 | /* Form container styling */ 14 | .bg-white { 15 | background-color: #ffffff; 16 | } 17 | 18 | .p-4 { 19 | padding: 1.5rem; 20 | } 21 | 22 | .rounded { 23 | border-radius: 0.25rem; 24 | } 25 | 26 | .shadow-sm { 27 | box-shadow: 0 0 0.125rem rgba(0, 0, 0, 0.2); 28 | } 29 | 30 | /* Form element styling */ 31 | .form-label { 32 | font-weight: 600; 33 | color: #333; 34 | } 35 | 36 | .form-control { 37 | border-radius: 0.25rem; 38 | box-shadow: none; 39 | } 40 | 41 | .form-check-input { 42 | margin-top: 0.3rem; 43 | } 44 | 45 | .btn { 46 | border-radius: 0.25rem; 47 | padding: 0.75rem 1.25rem; 48 | font-size: 1rem; 49 | } 50 | 51 | .btn-primary { 52 | background-color: #007bff; 53 | border-color: #007bff; 54 | } 55 | 56 | .btn-secondary { 57 | background-color: #6c757d; 58 | border-color: #6c757d; 59 | } 60 | 61 | .btn-secondary:hover { 62 | background-color: #5a6268; 63 | border-color: #545b62; 64 | } 65 | -------------------------------------------------------------------------------- /src/static/css/edit_website.css: -------------------------------------------------------------------------------- 1 | /* ping.css */ 2 | 3 | /* Edit form styling */ 4 | form { 5 | display: flex; 6 | flex-direction: column; 7 | align-items: center; 8 | margin-bottom: 20px; 9 | } 10 | 11 | form input, form button { 12 | padding: 10px; 13 | margin: 10px; 14 | border-radius: 5px; 15 | border: 1px solid #ccc; 16 | width: 300px; 17 | max-width: 100%; 18 | } 19 | 20 | form label { 21 | font-weight: bold; 22 | margin-bottom: 5px; 23 | } 24 | 25 | form button { 26 | background-color: #5cb85c; 27 | color: white; 28 | cursor: pointer; 29 | border: none; 30 | font-weight: bold; 31 | } 32 | 33 | form button:hover { 34 | background-color: #4cae4c; 35 | } 36 | 37 | /* Edit form back link */ 38 | a { 39 | display: inline-block; 40 | margin-top: 20px; 41 | text-decoration: none; 42 | color: #007bff; 43 | } 44 | 45 | a:hover { 46 | text-decoration: underline; 47 | } 48 | -------------------------------------------------------------------------------- /src/static/css/error.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/src/static/css/error.css -------------------------------------------------------------------------------- /src/static/css/experimental.css: -------------------------------------------------------------------------------- 1 | /* dashboard.css */ 2 | 3 | /* General container styling */ 4 | .container { 5 | padding: 20px; 6 | } 7 | 8 | /* Grid layout for cards */ 9 | .grid-container { 10 | display: grid; 11 | grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); 12 | gap: 20px; 13 | } 14 | 15 | /* Card styles */ 16 | .card { 17 | border-radius: 8px; 18 | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); 19 | padding: 20px; 20 | color: #ffffff; /* Ensure text color contrasts well with the card color */ 21 | transition: transform 0.2s ease; 22 | } 23 | 24 | .card.small { 25 | width: 150px; 26 | } 27 | 28 | .card.medium { 29 | width: 250px; 30 | } 31 | 32 | .card.large { 33 | width: 350px; 34 | } 35 | 36 | .card-header { 37 | font-size: 18px; 38 | margin-bottom: 10px; 39 | font-weight: bold; 40 | } 41 | 42 | .card-body { 43 | font-size: 16px; 44 | } 45 | 46 | .card-footer { 47 | margin-top: 10px; 48 | } 49 | 50 | /* Positioning based on card_position attribute */ 51 | .position-0 { 52 | grid-column: span 1; 53 | } 54 | 55 | .position-1 { 56 | grid-column: span 2; 57 | } 58 | 59 | .position-2 { 60 | grid-column: span 3; 61 | } 62 | 63 | /* Add more positioning styles as needed */ 64 | -------------------------------------------------------------------------------- /src/static/css/external_monitoring.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #f8f9fa; 3 | } 4 | 5 | .container { 6 | max-width: 600px; 7 | margin: auto; 8 | } 9 | 10 | .card { 11 | border: 1px solid #ced4da; 12 | border-radius: 0.5rem; 13 | } 14 | 15 | .card-title { 16 | font-weight: bold; 17 | } 18 | 19 | .message { 20 | color: #28a745; /* Success message color */ 21 | } 22 | 23 | .list-group-item { 24 | background-color: #ffffff; 25 | border: 1px solid #e9ecef; 26 | border-radius: 0.5rem; 27 | } 28 | 29 | .list-group-item:hover { 30 | background-color: #f1f1f1; 31 | } 32 | 33 | .btn-primary { 34 | background-color: #007bff; 35 | border: none; 36 | } 37 | 38 | .btn-danger { 39 | background-color: #dc3545; 40 | border: none; 41 | } 42 | -------------------------------------------------------------------------------- /src/static/css/footer.css: -------------------------------------------------------------------------------- 1 | body, html { 2 | height: 100%; 3 | margin: 0; 4 | } 5 | 6 | .container { 7 | min-height: 100%; 8 | flex-direction: column; 9 | } 10 | 11 | .content { 12 | flex: 1; 13 | /* Other content styling */ 14 | } 15 | 16 | footer { 17 | background-color: #333; 18 | color: white; 19 | text-align: center; 20 | padding: 10px; 21 | position: relative; 22 | width: 100%; 23 | bottom: 0; 24 | } 25 | 26 | footer a { 27 | color: white; 28 | text-decoration: none; 29 | } 30 | 31 | footer a:hover { 32 | text-decoration: underline; 33 | } 34 | -------------------------------------------------------------------------------- /src/static/css/new_alert_rules.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: Arial, sans-serif; 3 | background-color: #f8f9fa; 4 | margin: 0; 5 | padding: 20px; 6 | } 7 | 8 | h1 { 9 | color: #333; 10 | margin-bottom: 20px; 11 | } 12 | 13 | form { 14 | background-color: #ffffff; 15 | padding: 20px; 16 | border-radius: 8px; 17 | box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); 18 | } 19 | 20 | label { 21 | display: block; 22 | margin: 10px 0 5px; 23 | font-weight: bold; 24 | color: #495057; 25 | } 26 | 27 | input, 28 | textarea { 29 | width: 100%; 30 | padding: 10px; 31 | margin-bottom: 15px; 32 | border: 1px solid #ced4da; 33 | border-radius: 4px; 34 | font-size: 16px; 35 | } 36 | 37 | input:focus, 38 | textarea:focus { 39 | border-color: #80bdff; 40 | outline: none; 41 | box-shadow: 0 0 5px rgba(0, 123, 255, 0.25); 42 | } 43 | 44 | button { 45 | padding: 10px 15px; 46 | background-color: #007bff; 47 | color: white; 48 | border: none; 49 | border-radius: 4px; 50 | cursor: pointer; 51 | font-size: 16px; 52 | transition: background-color 0.3s; 53 | } 54 | 55 | button:hover { 56 | background-color: #0056b3; 57 | } 58 | 59 | #response { 60 | margin-top: 20px; 61 | font-size: 16px; 62 | } 63 | -------------------------------------------------------------------------------- /src/static/css/os_info.css: -------------------------------------------------------------------------------- 1 | /* General container styles */ 2 | .container { 3 | background-color: #f8f9fa; 4 | padding: 30px; 5 | border-radius: 12px; 6 | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); 7 | } 8 | 9 | /* Title styling */ 10 | h1 { 11 | font-size: 2.25rem; 12 | font-weight: 700; 13 | color: #495057; 14 | text-align: center; 15 | margin-bottom: 30px; 16 | } 17 | 18 | /* Table styles */ 19 | .table { 20 | background-color: #ffffff; 21 | border-radius: 8px; 22 | overflow: hidden; 23 | box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); 24 | margin-top: 20px; 25 | border: none; 26 | } 27 | 28 | /* Header of the table */ 29 | .table thead th { 30 | background-color: #6c757d; 31 | color: #fff; 32 | text-transform: uppercase; 33 | font-size: 0.875rem; 34 | letter-spacing: 0.05em; 35 | border-bottom: none; 36 | padding: 15px; 37 | text-align: left; 38 | } 39 | 40 | /* Table body cells */ 41 | .table tbody td { 42 | padding: 15px; 43 | vertical-align: middle; 44 | font-size: 0.875rem; 45 | border-color: #dee2e6; 46 | } 47 | 48 | /* Table icons */ 49 | .table tbody td i { 50 | margin-right: 8px; 51 | color: #007bff; /* Icon color */ 52 | } 53 | 54 | /* Hover effect for table rows */ 55 | .table-hover tbody tr:hover { 56 | background-color: #f1f1f1; 57 | } 58 | 59 | /* Alternating row colors for table */ 60 | .table-striped tbody tr:nth-of-type(odd) { 61 | background-color: #f9f9f9; 62 | } 63 | -------------------------------------------------------------------------------- /src/static/css/refresher.css: -------------------------------------------------------------------------------- 1 | /* Container for the select input */ 2 | .selector-container { 3 | display: flex; /* Use flexbox for alignment */ 4 | justify-content: flex-end; /* Align items to the right */ 5 | padding: 10px; /* Add some padding for spacing */ 6 | } 7 | 8 | /* Styling the select input */ 9 | #refresh-interval { 10 | padding: 5px 8px; /* Adjust padding for a smaller look */ 11 | font-size: 14px; /* Smaller font size */ 12 | border-radius: 4px; /* Rounded corners */ 13 | border: 1px solid #ccc; /* Light border */ 14 | outline: none; /* Remove default focus outline */ 15 | background-color: #fff; /* White background */ 16 | cursor: pointer; /* Pointer cursor for better UX */ 17 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* Subtle shadow */ 18 | transition: border-color 0.3s ease, box-shadow 0.3s ease; /* Smooth transition */ 19 | } 20 | 21 | /* Hover and focus styles for better interactivity */ 22 | #refresh-interval:hover, #refresh-interval:focus { 23 | border-color: #007bff; /* Border color change on hover */ 24 | box-shadow: 0 2px 8px rgba(0, 123, 255, 0.2); /* More pronounced shadow */ 25 | } 26 | -------------------------------------------------------------------------------- /src/static/css/send_email.css: -------------------------------------------------------------------------------- 1 | .email-container { 2 | max-width: 600px; 3 | margin: 0 auto; 4 | padding: 30px; 5 | background-color: #ffffff; 6 | border-radius: 12px; 7 | box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1); 8 | border: 1px solid #e0e0e0; 9 | margin-top: 50px; 10 | } 11 | 12 | h2 { 13 | margin-bottom: 20px; 14 | color: #343a40; 15 | font-size: 28px; 16 | font-weight: 700; 17 | display: flex; 18 | align-items: center; 19 | gap: 10px; 20 | } 21 | 22 | h2 i { 23 | color: #007bff; 24 | } 25 | 26 | .form-group { 27 | margin-bottom: 20px; 28 | } 29 | 30 | .form-group label { 31 | font-weight: 600; 32 | color: #495057; 33 | display: block; 34 | margin-bottom: 8px; 35 | } 36 | 37 | .form-group input, 38 | .form-group textarea, 39 | .form-group select { 40 | width: 100%; 41 | padding: 12px; 42 | border: 1px solid #ced4da; 43 | border-radius: 8px; 44 | background-color: #f8f9fa; 45 | font-size: 16px; 46 | box-sizing: border-box; 47 | transition: border-color 0.3s ease, box-shadow 0.3s ease; 48 | } 49 | 50 | .form-group input:focus, 51 | .form-group textarea:focus, 52 | .form-group select:focus { 53 | border-color: #007bff; 54 | box-shadow: 0 0 5px rgba(0, 123, 255, 0.3); 55 | } 56 | 57 | .btn-primary { 58 | padding: 12px 24px; 59 | background-color: #007bff; 60 | color: #ffffff; 61 | border: none; 62 | border-radius: 8px; 63 | cursor: pointer; 64 | font-size: 16px; 65 | text-align: center; 66 | transition: background-color 0.3s ease, transform 0.2s ease; 67 | display: flex; 68 | align-items: center; 69 | gap: 10px; 70 | } 71 | 72 | .btn-primary i { 73 | font-size: 18px; 74 | } 75 | 76 | .btn-primary:hover { 77 | background-color: #0056b3; 78 | transform: scale(1.05); 79 | } 80 | 81 | @media (max-width: 768px) { 82 | .email-container { 83 | padding: 20px; 84 | } 85 | 86 | h2 { 87 | font-size: 24px; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/static/css/show_alert.css: -------------------------------------------------------------------------------- 1 | /* Styles for the alert table */ 2 | table { 3 | width: 100%; 4 | border-collapse: collapse; 5 | margin: 20px 0; 6 | font-size: 18px; 7 | text-align: left; 8 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); 9 | } 10 | 11 | table, th, td { 12 | border: 1px solid #ddd; 13 | } 14 | 15 | th, td { 16 | padding: 12px 15px; 17 | text-align: left; 18 | } 19 | 20 | th { 21 | background-color: #f4f4f4; 22 | font-weight: bold; 23 | } 24 | 25 | td a { 26 | color: #3498db; 27 | text-decoration: none; 28 | } 29 | 30 | td a:hover { 31 | text-decoration: underline; 32 | } 33 | 34 | tbody tr:nth-child(even) { 35 | background-color: #f9f9f9; 36 | } 37 | 38 | tbody tr:hover { 39 | background-color: #f1f1f1; 40 | } 41 | 42 | /* Header */ 43 | h1 { 44 | font-size: 24px; 45 | color: #333; 46 | text-align: center; 47 | margin-bottom: 20px; 48 | font-weight: bold; 49 | } 50 | 51 | /* Page container */ 52 | body { 53 | font-family: Arial, sans-serif; 54 | background-color: #f0f0f5; 55 | margin: 0; 56 | padding: 0; 57 | } 58 | 59 | .container { 60 | width: 80%; 61 | margin: 0 auto; 62 | padding-top: 50px; 63 | } 64 | -------------------------------------------------------------------------------- /src/static/css/smtp_config.css: -------------------------------------------------------------------------------- 1 | .update-container { 2 | max-width: 500px; 3 | margin: 0 auto; 4 | padding: 20px; 5 | background-color: #f8f9fa; 6 | border-radius: 8px; 7 | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); 8 | margin-top: 50px; 9 | } 10 | 11 | h2 { 12 | text-align: center; 13 | color: #343a40; 14 | margin-bottom: 20px; 15 | } 16 | 17 | .form-group { 18 | margin-bottom: 15px; 19 | } 20 | 21 | .form-group label { 22 | display: block; 23 | font-weight: bold; 24 | color: #495057; 25 | } 26 | 27 | .form-group input { 28 | width: 100%; 29 | padding: 10px; 30 | border: 1px solid #ced4da; 31 | border-radius: 4px; 32 | } 33 | 34 | .btn-primary { 35 | width: 100%; 36 | padding: 10px; 37 | background-color: #007bff; 38 | color: #ffffff; 39 | border: none; 40 | border-radius: 4px; 41 | cursor: pointer; 42 | } 43 | 44 | .btn-primary:hover { 45 | background-color: #0056b3; 46 | } 47 | -------------------------------------------------------------------------------- /src/static/css/speedtest_error.css: -------------------------------------------------------------------------------- 1 | 2 | .error-container { 3 | background-color: #f8d7da; 4 | border: 1px solid #f5c6cb; 5 | padding: 20px; 6 | border-radius: 10px; 7 | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); 8 | text-align: center; 9 | } 10 | 11 | .error-title { 12 | font-size: 2rem; 13 | margin-bottom: 10px; 14 | font-weight: bold; 15 | } 16 | 17 | .error-message { 18 | font-size: 1.25rem; 19 | margin-bottom: 20px; 20 | } 21 | 22 | .retry-button { 23 | background-color: #dc3545; 24 | color: white; 25 | padding: 10px 20px; 26 | text-decoration: none; 27 | border-radius: 5px; 28 | transition: background-color 0.3s ease; 29 | } 30 | 31 | .retry-button:hover { 32 | background-color: #c82333; 33 | } -------------------------------------------------------------------------------- /src/static/css/tab_navigation.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeperfectplus/SystemGuard/3692857c266de10d4cf9310c815097ed69064e6c/src/static/css/tab_navigation.css -------------------------------------------------------------------------------- /src/static/css/terminal.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: monospace; 3 | background-color: #000; 4 | color: #0f0; 5 | margin: 0; 6 | padding: 20px; 7 | } 8 | 9 | #terminal { 10 | background-color: #000; 11 | color: #0f0; 12 | padding: 10px; 13 | border: 1px solid #0f0; 14 | height: 400px; 15 | overflow-y: auto; 16 | margin-top: 50px; 17 | } 18 | 19 | #command { 20 | width: 100%; 21 | background-color: #000; 22 | color: #0f0; 23 | border: none; 24 | outline: none; 25 | font-size: 16px; 26 | } -------------------------------------------------------------------------------- /src/static/css/terms.css: -------------------------------------------------------------------------------- 1 | .terms-container { 2 | max-width: 800px; 3 | margin: 50px auto; 4 | padding: 30px; 5 | background-color: #ffffff; 6 | border-radius: 8px; 7 | box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); 8 | } 9 | 10 | h2 { 11 | font-size: 32px; 12 | color: #343a40; 13 | margin-bottom: 20px; 14 | } 15 | 16 | h3 { 17 | font-size: 22px; 18 | color: #007bff; 19 | margin-top: 20px; 20 | } 21 | 22 | p { 23 | font-size: 16px; 24 | color: #6c757d; 25 | line-height: 1.6; 26 | } 27 | 28 | a { 29 | display: block; 30 | margin-top: 30px; 31 | font-size: 16px; 32 | color: #007bff; 33 | text-align: center; 34 | } 35 | -------------------------------------------------------------------------------- /src/static/css/time_filter.css: -------------------------------------------------------------------------------- 1 | /* Container for the select input */ 2 | .selector-container { 3 | display: flex; /* Use flexbox for alignment */ 4 | justify-content: flex-end; /* Align items to the right */ 5 | padding: 10px; /* Add some padding for spacing */ 6 | } 7 | 8 | /* Styling the select input */ 9 | #timeFilter { 10 | padding: 5px 8px; /* Adjust padding for a smaller look */ 11 | font-size: 14px; /* Smaller font size */ 12 | border-radius: 4px; /* Rounded corners */ 13 | border: 1px solid #ccc; /* Light border */ 14 | outline: none; /* Remove default focus outline */ 15 | background-color: #fff; /* White background */ 16 | cursor: pointer; /* Pointer cursor for better UX */ 17 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* Subtle shadow */ 18 | transition: border-color 0.3s ease, box-shadow 0.3s ease; /* Smooth transition */ 19 | } 20 | 21 | /* Hover and focus styles for better interactivity */ 22 | #timeFilter:hover, #timeFilter:focus { 23 | border-color: #007bff; /* Border color change on hover */ 24 | box-shadow: 0 2px 8px rgba(0, 123, 255, 0.2); /* More pronounced shadow */ 25 | } 26 | -------------------------------------------------------------------------------- /src/static/css/update_card.css: -------------------------------------------------------------------------------- 1 | .container { 2 | max-width: 800px; 3 | margin: auto; 4 | padding: 20px; 5 | background-color: #f9f9f9; 6 | border-radius: 8px; 7 | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); 8 | margin-top: 20px; 9 | } 10 | 11 | h1 { 12 | font-size: 2em; 13 | margin-bottom: 20px; 14 | } 15 | 16 | .form-group { 17 | margin-bottom: 15px; 18 | } 19 | 20 | .form-group label { 21 | display: block; 22 | font-weight: bold; 23 | margin-bottom: 5px; 24 | } 25 | 26 | .form-group input[type="text"], 27 | .form-group input[type="color"], 28 | .form-group input[type="number"], 29 | .form-group textarea, 30 | .form-group select { 31 | width: 100%; 32 | padding: 8px; 33 | border: 1px solid #ddd; 34 | border-radius: 4px; 35 | } 36 | 37 | .form-group textarea { 38 | height: 100px; 39 | } 40 | 41 | .btn { 42 | padding: 10px 20px; 43 | font-size: 16px; 44 | color: #ffffff; 45 | background-color: #007bff; 46 | border: none; 47 | border-radius: 4px; 48 | cursor: pointer; 49 | transition: background-color 0.3s ease; 50 | } 51 | 52 | .btn:hover { 53 | background-color: #0056b3; 54 | } 55 | -------------------------------------------------------------------------------- /src/static/css/update_webhooks.css: -------------------------------------------------------------------------------- 1 | .container { 2 | margin: auto; 3 | animation: fadeInUp 0.5s ease-in-out; 4 | } 5 | 6 | .card { 7 | background-color: #ffffff; 8 | border-radius: 12px; 9 | padding: 30px; 10 | box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1); 11 | } 12 | 13 | h2 { 14 | font-size: 2rem; 15 | font-weight: 600; 16 | color: #333; 17 | margin-bottom: 20px; 18 | text-align: center; 19 | } 20 | 21 | p { 22 | color: #555; 23 | font-size: 1rem; 24 | margin-bottom: 20px; 25 | text-align: center; 26 | } 27 | 28 | label { 29 | font-weight: 550; 30 | color: #444; 31 | margin-bottom: 10px; 32 | padding: auto; 33 | text-align: left; 34 | 35 | } 36 | 37 | input[type="url"], 38 | input[type="text"] { 39 | transition: border-color 0.3s, box-shadow 0.3s; 40 | border: 1px solid #ced4da; 41 | border-radius: 5px; 42 | padding: 10px; 43 | width: 100%; 44 | margin-bottom: 10px; 45 | } 46 | 47 | input[type="url"]:focus, 48 | input[type="text"]:focus { 49 | border-color: #007bff; 50 | box-shadow: 0 0 10px rgba(0, 123, 255, 0.2); 51 | } 52 | 53 | .btn-primary { 54 | background-color: #007bff; 55 | border-color: #007bff; 56 | transition: background-color 0.3s, transform 0.3s; 57 | width: 100%; 58 | font-size: 1.1rem; 59 | font-weight: 600; 60 | } 61 | 62 | .btn-primary:hover { 63 | background-color: #0056b3; 64 | transform: translateY(-2px); 65 | } 66 | 67 | .form-group { 68 | margin-bottom: 1.5rem; 69 | } 70 | 71 | @keyframes fadeInUp { 72 | from { 73 | opacity: 0; 74 | transform: translateY(50px); 75 | } 76 | to { 77 | opacity: 1; 78 | transform: translateY(0); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/static/css/utility.css: -------------------------------------------------------------------------------- 1 | /* Container Styles */ 2 | /* .container { 3 | background-color: #f9f9f9; 4 | padding: 20px; 5 | max-width: 500px; 6 | margin: 0 auto; 7 | border-radius: 10px; 8 | box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); 9 | margin-top: 50px; 10 | } */ 11 | 12 | /* Title Styles */ 13 | .settings-title { 14 | font-size: 32px; 15 | color: #2c3e50; 16 | margin-bottom: 30px; 17 | text-align: center; 18 | text-transform: uppercase; 19 | letter-spacing: 1px; 20 | } 21 | 22 | /* Form Styles */ 23 | .control-form { 24 | padding: 20px; 25 | } 26 | 27 | .form-group { 28 | margin-bottom: 25px; 29 | } 30 | 31 | .form-control { 32 | font-size: 18px; 33 | padding: 15px; 34 | border-radius: 6px; 35 | border: 1px solid #ddd; 36 | } 37 | 38 | .form-control:focus { 39 | border-color: #2980b9; 40 | box-shadow: 0 0 5px rgba(41, 128, 185, 0.3); 41 | } 42 | 43 | /* Button Styles */ 44 | .btn { 45 | font-size: 18px; 46 | padding: 15px; 47 | border-radius: 8px; 48 | transition: all 0.3s ease; 49 | } 50 | 51 | .btn-lg { 52 | width: 100%; 53 | } 54 | 55 | .btn-danger { 56 | background-color: #e74c3c; 57 | border: none; 58 | } 59 | 60 | .btn-danger:hover { 61 | background-color: #c0392b; 62 | } 63 | 64 | .btn-warning { 65 | background-color: #f39c12; 66 | border: none; 67 | } 68 | 69 | .btn-warning:hover { 70 | background-color: #e67e22; 71 | } 72 | 73 | .btn-secondary { 74 | background-color: #7f8c8d; 75 | border: none; 76 | } 77 | 78 | .btn-secondary:hover { 79 | background-color: #95a5a6; 80 | } 81 | 82 | /* Flash Message Styles */ 83 | .alert-container { 84 | margin-top: 20px; 85 | } 86 | 87 | .alert { 88 | font-size: 16px; 89 | padding: 12px; 90 | border-radius: 6px; 91 | width: 100%; 92 | margin-bottom: 20px; 93 | } 94 | -------------------------------------------------------------------------------- /src/static/css/view_rules.css: -------------------------------------------------------------------------------- 1 | .rules-container { 2 | width: 90%; 3 | margin: 0 auto; 4 | background: #fff; 5 | padding: 20px; 6 | border-radius: 8px; 7 | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); 8 | } 9 | 10 | .group-section { 11 | margin-bottom: 30px; 12 | } 13 | 14 | .rule-list { 15 | list-style: none; 16 | padding-left: 0; 17 | } 18 | 19 | .rule-item { 20 | background-color: #e9ecef; 21 | padding: 15px; 22 | border-radius: 6px; 23 | margin-bottom: 10px; 24 | transition: all 0.3s ease; 25 | } 26 | 27 | .rule-header { 28 | display: flex; 29 | justify-content: space-between; 30 | align-items: center; 31 | } 32 | 33 | .rule-name { 34 | font-weight: bold; 35 | font-size: 1.2rem; 36 | color: #333; 37 | } 38 | 39 | .rule-state { 40 | font-size: 0.9rem; 41 | padding: 5px 10px; 42 | border-radius: 5px; 43 | } 44 | 45 | .rule-state.firing { 46 | background-color: #dc3545; 47 | color: #fff; 48 | } 49 | 50 | .rule-state.inactive { 51 | background-color: #28a745; 52 | color: #fff; 53 | } 54 | 55 | .rule-state.pending { 56 | background-color: #ffc107; 57 | color: #333; 58 | } 59 | 60 | .rule-details-container { 61 | max-height: 0; 62 | overflow: hidden; 63 | transition: max-height 0.3s ease; 64 | } 65 | 66 | .rule-details { 67 | list-style: none; 68 | padding-left: 0; 69 | margin-top: 10px; 70 | } 71 | 72 | .toggle-details-btn { 73 | background-color: #007bff; 74 | color: white; 75 | border: none; 76 | padding: 5px 10px; 77 | cursor: pointer; 78 | border-radius: 5px; 79 | font-size: 0.9rem; 80 | } 81 | 82 | .toggle-details-btn:hover { 83 | background-color: #0056b3; 84 | } 85 | 86 | .alert-list { 87 | list-style: none; 88 | padding-left: 0; 89 | } 90 | 91 | .alert-item { 92 | background-color: #f1f3f5; 93 | padding: 10px; 94 | border-radius: 4px; 95 | margin-bottom: 8px; 96 | } 97 | -------------------------------------------------------------------------------- /src/static/css/view_users.css: -------------------------------------------------------------------------------- 1 | /* view_users.css */ 2 | 3 | .view-users-container { 4 | padding: 20px; 5 | max-width: 1200px; 6 | margin: 0 auto; 7 | background-color: #ffffff; 8 | border: 1px solid #ddd; 9 | border-radius: 8px; 10 | box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); 11 | } 12 | 13 | .page-title { 14 | margin-bottom: 20px; 15 | font-size: 24px; 16 | font-weight: bold; 17 | color: #333; 18 | display: flex; 19 | justify-content: space-between; 20 | align-items: center; 21 | } 22 | 23 | .btn-add-user { 24 | background-color: #28a745; 25 | color: white; 26 | padding: 10px 20px; 27 | text-decoration: none; 28 | border-radius: 4px; 29 | font-size: 16px; 30 | display: inline-block; 31 | margin-top: 10px; 32 | margin-bottom: 10px; 33 | } 34 | 35 | .btn-add-user:hover { 36 | background-color: #218838; 37 | } 38 | 39 | .user-table { 40 | width: 100%; 41 | border-collapse: collapse; 42 | } 43 | 44 | .user-table th, .user-table td { 45 | border: 1px solid #ddd; 46 | padding: 12px; 47 | text-align: left; 48 | } 49 | 50 | .user-table th { 51 | background-color: #f4f4f4; 52 | font-weight: bold; 53 | } 54 | 55 | .user-table tr:nth-child(even) { 56 | background-color: #f9f9f9; 57 | } 58 | 59 | .user-table tr:hover { 60 | background-color: #f1f1f1; 61 | } 62 | 63 | .btn-edit { 64 | background-color: #007bff; 65 | color: white; 66 | padding: 8px 12px; 67 | text-decoration: none; 68 | border-radius: 4px; 69 | } 70 | 71 | .btn-edit:hover { 72 | background-color: #0056b3; 73 | } 74 | 75 | .btn-delete { 76 | background-color: #dc3545; 77 | color: white; 78 | padding: 8px 12px; 79 | border: none; 80 | border-radius: 4px; 81 | cursor: pointer; 82 | font-size: 14px; 83 | } 84 | 85 | .btn-delete:hover { 86 | background-color: #c82333; 87 | } 88 | -------------------------------------------------------------------------------- /src/static/js/checkPassword.js: -------------------------------------------------------------------------------- 1 | document.getElementById('password').addEventListener('input', function() { 2 | let strengthMeter = document.getElementById('password-strength'); 3 | let password = this.value; 4 | if (password.length >= 8) { 5 | strengthMeter.textContent = 'Strong'; 6 | strengthMeter.style.color = 'green'; 7 | } else if (password.length >= 4) { 8 | strengthMeter.textContent = 'Moderate'; 9 | strengthMeter.style.color = 'orange'; 10 | } else { 11 | strengthMeter.textContent = 'Weak'; 12 | strengthMeter.style.color = 'red'; 13 | } 14 | }); 15 | 16 | document.getElementById('confirm_password').addEventListener('input', function() { 17 | let matchStatus = document.getElementById('password-match'); 18 | if (this.value === document.getElementById('password').value) { 19 | matchStatus.textContent = 'Passwords match'; 20 | matchStatus.style.color = 'green'; 21 | } else { 22 | matchStatus.textContent = 'Passwords do not match'; 23 | matchStatus.style.color = 'red'; 24 | } 25 | }); 26 | -------------------------------------------------------------------------------- /src/static/js/main.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("DOMContentLoaded", function () { 2 | // Select all card elements on the page 3 | const cards = document.querySelectorAll('.card'); 4 | 5 | cards.forEach((card) => { 6 | // Create a new element for the text 7 | const providerText = document.createElement('p'); 8 | providerText.classList.add('data-provider-text'); 9 | providerText.innerHTML = 'Powered by SystemGuard'; 10 | 11 | // Append the text element to the card 12 | card.appendChild(providerText); 13 | }); 14 | 15 | // Initialize all Bootstrap tooltips 16 | const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]'); 17 | tooltipTriggerList.forEach((tooltipTriggerEl) => { 18 | new bootstrap.Tooltip(tooltipTriggerEl, { 19 | animation: true, 20 | delay: { show: 300, hide: 100 }, 21 | html: true, 22 | }); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /src/static/js/portUrlToggle.js: -------------------------------------------------------------------------------- 1 | function toggleFields() { 2 | var selection = document.getElementById('type_selection').value; 3 | var ipField = document.getElementById('ip_address'); 4 | var portField = document.getElementById('port'); 5 | var linkField = document.getElementById('link'); 6 | 7 | if (selection === 'link') { 8 | ipField.disabled = true; 9 | portField.disabled = true; 10 | linkField.disabled = false; 11 | document.getElementById('ip_group').style.display = 'none'; 12 | document.getElementById('port_group').style.display = 'none'; 13 | document.getElementById('link_group').style.display = 'block'; 14 | } else { 15 | ipField.disabled = false; 16 | portField.disabled = false; 17 | linkField.disabled = true; 18 | document.getElementById('ip_group').style.display = 'block'; 19 | document.getElementById('port_group').style.display = 'block'; 20 | document.getElementById('link_group').style.display = 'none'; 21 | } 22 | } 23 | 24 | window.onload = function () { 25 | toggleFields(); // Initialize the fields based on the current selection 26 | }; -------------------------------------------------------------------------------- /src/static/js/refreshPage.js: -------------------------------------------------------------------------------- 1 | let refreshInterval = 0; // Initialize with a default value 2 | let refreshTimeout; 3 | 4 | function fetchRefreshInterval() { 5 | fetch('/api/v1/refresh-interval') 6 | .then(response => response.json()) 7 | .then(data => { 8 | if (data.success) { 9 | refreshInterval = data.refresh_interval * 1000; // Multiply by 1000 to convert to milliseconds 10 | console.log('Refresh interval fetched successfully:', data.refresh_interval); 11 | startRefresh(); // Start refreshing after fetching the interval 12 | } else { 13 | console.error('Failed to fetch refresh interval:', data.error); 14 | } 15 | }) 16 | .catch(error => console.error('Error:', error)); 17 | } 18 | 19 | function startRefresh() { 20 | if (refreshInterval > 0) { // Only refresh if the interval is greater than 0 21 | refreshTimeout = setTimeout(function () { 22 | location.reload(); 23 | }, refreshInterval); 24 | } 25 | } 26 | 27 | // Start the process by fetching the refresh interval 28 | fetchRefreshInterval(); 29 | 30 | // Event listener for select input change 31 | document.getElementById('refresh-interval').addEventListener('change', function () { 32 | // Clear the existing timeout 33 | clearTimeout(refreshTimeout); 34 | 35 | // Update the interval based on the selected value 36 | refreshInterval = parseInt(this.value) * 1000; // Convert to milliseconds 37 | 38 | // Restart the refresh process if a valid interval is selected 39 | startRefresh(); 40 | 41 | // Send the updated refresh interval to the server 42 | fetch('/api/v1/refresh-interval', { 43 | method: 'POST', 44 | headers: { 45 | 'Content-Type': 'application/json' 46 | }, 47 | body: JSON.stringify({ refresh_interval: parseInt(this.value) }) // Send in seconds, not milliseconds 48 | }) 49 | .then(response => response.json()) 50 | .then(data => { 51 | if (data.success) { 52 | console.log('Refresh interval updated successfully:', data.refresh_interval); 53 | } else { 54 | console.error('Failed to update refresh interval:', data.error); 55 | } 56 | }) 57 | .catch(error => console.error('Error:', error)); 58 | }); 59 | -------------------------------------------------------------------------------- /src/static/js/terminal.js: -------------------------------------------------------------------------------- 1 | document.getElementById('terminal-form').addEventListener('submit', function (event) { 2 | event.preventDefault(); 3 | let command = document.getElementById('command').value; 4 | if (command.trim() !== '') { 5 | let terminal = document.getElementById('terminal'); 6 | terminal.innerHTML += `$ ${command}
`; 7 | document.getElementById('command').value = ''; 8 | 9 | fetch('/terminal', { 10 | method: 'POST', 11 | headers: { 12 | 'Content-Type': 'application/x-www-form-urlencoded', 13 | }, 14 | body: `command=${command}` 15 | }) 16 | .then(response => response.json()) 17 | .then(data => { 18 | terminal.innerHTML += `
${data.output}

`; 19 | terminal.scrollTop = terminal.scrollHeight; 20 | }); 21 | } 22 | }); -------------------------------------------------------------------------------- /src/static/js/update.js: -------------------------------------------------------------------------------- 1 | document.getElementById('updateButton').addEventListener('click', function (event) { 2 | event.preventDefault(); // Prevent the default link behavior 3 | 4 | fetch('{{ url_for("update_git_version") }}', { 5 | method: 'POST', 6 | headers: { 7 | 'Content-Type': 'application/json', 8 | // Add any additional headers if needed 9 | }, 10 | }) 11 | .then(response => response.json()) 12 | .then(data => { 13 | if (data.status === 'success') { 14 | alert('Update successful: ' + data.message); 15 | } else { 16 | alert('Update failed: ' + data.message); 17 | } 18 | }) 19 | .catch(error => { 20 | console.error('Error:', error); 21 | alert('An error occurred while updating.'); 22 | }); 23 | }); -------------------------------------------------------------------------------- /src/static/js/updateRefreshInterval.js: -------------------------------------------------------------------------------- 1 | // let refreshInterval = {{ user_dashboard_settings.refresh_interval * 1000 }}; // Multiply by 1000 initially 2 | 3 | // Fetch the refresh interval from the server 4 | fetch('/api/v1/refresh-interval') 5 | .then(response => response.json()) 6 | .then(data => { 7 | if (data.success) { 8 | refreshInterval = data.refresh_interval * 1000; // Multiply by 1000 to convert to milliseconds 9 | console.log('Refresh interval fetched successfully:', data.refresh_interval); 10 | } else { 11 | console.error('Failed to fetch refresh interval:', data.error); 12 | } 13 | }) 14 | .catch(error => console.error('Error:', error)); 15 | 16 | let refreshTimeout; 17 | 18 | // Event listener for select input change 19 | document.getElementById('refresh-interval').addEventListener('change', function () { 20 | // Clear the existing timeout 21 | clearTimeout(refreshTimeout); 22 | 23 | // Update the interval based on the selected value 24 | refreshInterval = parseInt(this.value) * 1000; // Convert to milliseconds 25 | 26 | // refresh the page once 27 | refreshTimeout = setTimeout(() => { 28 | window.location.reload(); 29 | }, refreshInterval); 30 | 31 | // Send the updated refresh interval to the server 32 | fetch('/api/v1/refresh-interval', { 33 | method: 'POST', 34 | headers: { 35 | 'Content-Type': 'application/json' 36 | }, 37 | body: JSON.stringify({ refresh_interval: parseInt(this.value) }) // Send in seconds, not milliseconds 38 | }) 39 | .then(response => response.json()) 40 | .then(data => { 41 | if (data.success) { 42 | console.log('Refresh interval updated successfully:', data.refresh_interval); 43 | } else { 44 | console.error('Failed to update refresh interval:', data.error); 45 | } 46 | }) 47 | .catch(error => console.error('Error:', error)); 48 | }); 49 | -------------------------------------------------------------------------------- /src/templates/alerts/active_alerts.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Active Alerts{% endblock %} 3 | 4 | {% block extra_head %} 5 | 6 | {% endblock %} 7 | {% block content %} 8 |

Active Alerts

9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% for alert in alerts %} 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {% else %} 33 | 34 | 35 | 36 | {% endfor %} 37 | 38 |
Alert NameInstanceSeverityDescriptionSummaryStatusActive Since
{{ alert.labels.alertname }}{{ alert.labels.instance }}{{ alert.labels.severity }}{{ alert.annotations.description }}{{ alert.annotations.summary }}{{ alert.state }}{{ alert.activeAt }}
No active alerts
39 | {% endblock %} 40 | -------------------------------------------------------------------------------- /src/templates/alerts/alertmanager_status.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Alertmanager Status{% endblock %} 3 | 4 | {% block extra_head %} 5 | 6 | {% endblock %} 7 | 8 | {% block content %} 9 |
10 |

Alertmanager Status

11 | 12 | {% if alertmanagers %} 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {% for alertmanager in alertmanagers %} 22 | 23 | 24 | 25 | 26 | {% endfor %} 27 | 28 |
URLCluster
{{ alertmanager.url }}{{ alertmanager.cluster }}
29 | {% else %} 30 |

No active Alertmanagers found.

31 | {% endif %} 32 |
33 | {% endblock %} 34 | -------------------------------------------------------------------------------- /src/templates/alerts/show_alerts.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Update Email & Password{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | {% block content %} 7 |

Alert Manager

8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% for alert in alerts %} 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | {% endfor %} 34 | 35 |
Alert NameInstanceSeverityDescriptionStatusStarts AtEnds AtGenerator URL
{{ alert.labels.alertname }}{{ alert.labels.instance }}{{ alert.labels.severity }}{{ alert.annotations.description }}{{ alert.status.state }}{{ alert.startsAt }}{{ alert.endsAt }}View
36 | {% endblock %} -------------------------------------------------------------------------------- /src/templates/auths/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Login{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | {% block content %} 7 | 31 | {% endblock %} 32 | -------------------------------------------------------------------------------- /src/templates/base/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% block title %}System Dashboard{% endblock %} 8 | 9 | 10 | 11 | 12 | 13 | 14 | {% block extra_head %}{% endblock %} 15 | 16 | 17 | {% include 'ext/navbar.html' %} 18 |
19 | {% block content %} 20 | {% endblock %} 21 |
22 | 23 | 24 | 25 | 26 | 27 | {% block extra_scripts %}{% endblock %} 28 | {% include 'ext/footer.html' %} 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/templates/card_comp/battery/percentage.html: -------------------------------------------------------------------------------- 1 | {% if card_settings.is_battery_card_enabled %} 2 |
3 |
4 |
5 | Battery Percentage 6 | {% if system_info['battery_percent'] > 50 %} 7 | 8 | {% elif system_info['battery_percent'] > 25 %} 9 | 10 | {% else %} 11 | 12 | {% endif %} 13 |
14 |

{{ system_info['battery_percent'] }}%

15 |
16 |
17 |
18 | 19 |
20 |
21 | {% endif %} 22 | -------------------------------------------------------------------------------- /src/templates/card_comp/cpu/core.html: -------------------------------------------------------------------------------- 1 | {% if card_settings.is_cpu_core_card_enabled %} 2 | 3 |
4 |
5 |
{{ system_info['cpu_core'] }} CPU Cores
6 |
7 | {% for i in range(system_info['cpu_core']) %} 8 |
9 | {% endfor %} 10 |
11 |
12 |
13 | {% endif %} 14 | -------------------------------------------------------------------------------- /src/templates/card_comp/cpu/critical_temp.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
CPU High Temperature
4 |

5 | {{ system_info['high_temp'] }} °C 6 |

7 |
8 |
9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /src/templates/card_comp/cpu/current_temp.html: -------------------------------------------------------------------------------- 1 | {% if card_settings.is_cpu_temp_card_enabled %} 2 |
5 |
6 |
CPU Temperature
7 |

{{ system_info['current_temp'] }} °C

8 |
9 |
10 |
11 | 12 |
13 |
14 | {% endif %} 15 | 16 | 17 | 24 | -------------------------------------------------------------------------------- /src/templates/card_comp/cpu/frequency.html: -------------------------------------------------------------------------------- 1 |
4 |
5 |
CPU Frequency
6 |

8 | {{ system_info['cpu_frequency'] }} 9 |

10 |
11 |
13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 | 27 | -------------------------------------------------------------------------------- /src/templates/card_comp/cpu/highest_temp.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
CPU High Temperature
4 |

5 | {{ system_info['high_temp'] }} °C 6 |

7 |
8 |
9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /src/templates/card_comp/cpu/usages.html: -------------------------------------------------------------------------------- 1 | {% if card_settings.is_cpu_usage_card_enabled %} 2 |
4 |
5 |
CPU Usage
6 |

7 | {{ system_info['cpu_percent'] }}% 8 |

9 |
10 |
11 |
12 | 13 | 14 |
15 |
16 | {% endif %} 17 | 24 | -------------------------------------------------------------------------------- /src/templates/card_comp/disk/free.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
Disk Free
4 |

{{ system_info['disk_free']}} GB

5 |
6 |
-------------------------------------------------------------------------------- /src/templates/card_comp/disk/total.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
Disk Total
4 |

{{ system_info['disk_total']}} GB

5 |
6 |
-------------------------------------------------------------------------------- /src/templates/card_comp/disk/usage.html: -------------------------------------------------------------------------------- 1 | {% if card_settings.is_disk_usage_card_enabled %} 2 |
3 |
4 |
Disk Usage
5 |

6 | {{ system_info['disk_percent'] }}% 7 |

8 |
9 |
10 |
11 | 12 | 13 |
14 |
15 | {% endif %} 16 | 17 | 24 | -------------------------------------------------------------------------------- /src/templates/card_comp/disk/used.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
Disk Used
4 |

{{ system_info['disk_used']}} GB

5 |
6 |
-------------------------------------------------------------------------------- /src/templates/card_comp/memory/available.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
Memory Available
4 |

{{ system_info['memory_available']}} GB

5 |
6 |
-------------------------------------------------------------------------------- /src/templates/card_comp/memory/dashboard_memory.html: -------------------------------------------------------------------------------- 1 | {% if card_settings.is_dashboard_memory_card_enabled %} 2 |
3 |
4 |
Memory ({{title}})
5 |

{{ system_info['dashboard_memory_usage']}} MB

6 |
7 |
8 | {% endif %} -------------------------------------------------------------------------------- /src/templates/card_comp/memory/swap_free.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
Free Swap Memory
4 |

{{ system_info['free_swap']}} GB

5 |
6 |
-------------------------------------------------------------------------------- /src/templates/card_comp/memory/swap_total.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
Total Swap Memory
4 |

{{ system_info['total_swap']}} GB

5 |
6 |
-------------------------------------------------------------------------------- /src/templates/card_comp/memory/swap_used.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
Used Swap Memory
4 |

{{ system_info['used_swap']}} GB

5 |
6 |
-------------------------------------------------------------------------------- /src/templates/card_comp/memory/usage.html: -------------------------------------------------------------------------------- 1 | {% if card_settings.is_memory_usage_card_enabled %} 2 |
5 |
6 |
Memory Usage
7 |

8 | {{ system_info['memory_percent'] }}% 9 |

10 |
11 |
12 |
13 | 14 | 15 |
16 |
17 | {% endif %} 18 | 19 | -------------------------------------------------------------------------------- /src/templates/card_comp/memory/used.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 | Memory Usage 6 | 7 |
8 | 9 | 10 |

11 | {{ system_info['memory_used'] }} GB 12 |

13 | 14 |

15 | Total Memory: {{ system_info['memory_available'] }} GB 16 |

17 |
18 |
19 | -------------------------------------------------------------------------------- /src/templates/card_comp/network/ipv4_ip.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
IPV4 Connections
4 |

{{ system_info['ipv4_ip']}}

5 |
6 |
-------------------------------------------------------------------------------- /src/templates/card_comp/network/ipv6_ip.html: -------------------------------------------------------------------------------- 1 |
IPV6 Connections

{{ system_info['ipv6_ip']}}

-------------------------------------------------------------------------------- /src/templates/card_comp/network/packets_received.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
Network Received
4 |

{{ system_info['network_received']}} MB

5 |
6 |
7 | -------------------------------------------------------------------------------- /src/templates/card_comp/network/packets_sent.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
Network Sent
4 |

{{ system_info['network_sent']}} MB

5 |
6 |
7 | -------------------------------------------------------------------------------- /src/templates/card_comp/network/stats.html: -------------------------------------------------------------------------------- 1 | {% if card_settings.is_network_statistic_card_enabled %} 2 |
4 |
5 |
Network Statistics
6 |

7 | D: {{ system_info['network_sent'] }} MB U: {{ 8 | system_info['network_received'] }} MB
9 |

10 |
11 |
12 |
13 |
14 |
15 |
16 | {% endif %} -------------------------------------------------------------------------------- /src/templates/card_comp/other/os_info.html: -------------------------------------------------------------------------------- 1 | {% if card_settings.is_user_card_enabled %} 2 |
3 |
4 | 5 |
6 | 7 | {{ system_info['os_info']['os_full_name'] }} 8 |
9 | 10 | 11 | 14 |
15 |
16 | {% endif %} 17 | -------------------------------------------------------------------------------- /src/templates/card_comp/other/server_node.html: -------------------------------------------------------------------------------- 1 | {% if card_settings.is_user_card_enabled %} 2 |
3 |
4 |
System Node
5 |

{{ system_ip_address }}

6 |
7 |
8 | {% endif %} -------------------------------------------------------------------------------- /src/templates/card_comp/other/server_time.html: -------------------------------------------------------------------------------- 1 | {% if card_settings.is_server_card_enabled %} 2 |
3 |
4 |
Server Time
5 |

{{ system_info['current_server_time'] }}

6 |
7 |
8 | {% endif %} 9 | -------------------------------------------------------------------------------- /src/templates/card_comp/other/speedtest.html: -------------------------------------------------------------------------------- 1 | {% if card_settings.is_speedtest_enabled %} 2 |
3 |
4 |
5 |
Perform Speed Test
6 | 7 | 8 | 11 | 12 | 13 |
14 | {% if not speedtest_result["show_prompt"] %} 15 |

16 | Download Speed: {{ speedtest_result["download_speed"] }} 17 |

18 |

19 | Upload Speed: {{ speedtest_result["upload_speed"] }} 20 |

21 |

22 | Test Last Performed: {{ last_timestamp }} 23 |

24 |

25 | Try again in: {{ speedtest_result["remaining_time_for_next_test"] }} mins 26 |

27 | {% endif %} 28 |
29 | 30 | 31 | {% if speedtest_result["show_prompt"] %} 32 | Run Speed Test 33 | {% endif %} 34 |
35 |
36 |
37 | {% endif %} 38 | 39 | 46 | -------------------------------------------------------------------------------- /src/templates/card_comp/other/uptime.html: -------------------------------------------------------------------------------- 1 | {% if card_settings.is_system_uptime_card_enabled %} 2 |
3 |
4 |
System Uptime
5 |

6 | {{ system_info['uptime_days'] }} days, {{ system_info['uptime_hours'] }} hours, 7 | {{ system_info['uptime_minutes'] }} minutes, {{ system_info['uptime_seconds'] }} seconds 8 |

9 |
10 |
11 | {% endif %} 12 | -------------------------------------------------------------------------------- /src/templates/card_comp/other/username.html: -------------------------------------------------------------------------------- 1 | {% if card_settings.is_user_card_enabled %} 2 |
3 |
4 | 5 | 8 | 9 | 10 |
11 |

12 | {{ system_info['system_username'] }} 13 | @{{ system_ip_address }} 14 |

15 |
16 |
17 |
18 | {% endif %} 19 | -------------------------------------------------------------------------------- /src/templates/card_comp/selector/refresh_button.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 13 |
14 |
15 | -------------------------------------------------------------------------------- /src/templates/email_templates/deletion_email.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Login Details Removed 7 | 39 | 40 | 41 |
42 |

Login Details Removed

43 |

Hello,

44 |

The login details for the following user have been removed from the database:

45 |

Username: {{ username }}

46 |

Deletion Time: {{ deletion_time }}

47 |

Deleted By: {{ current_user }}

48 |

If you did not authorize this action, please review your account security immediately.

49 | 53 |
54 | 55 | 56 | -------------------------------------------------------------------------------- /src/templates/email_templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Login Notification 8 | 43 | 44 | 45 | 46 |
47 |
48 | Login Notification 49 |
50 |
51 | Hello {{ username }},

52 | We noticed a login to your account on {{ login_time }}, This is a Notification that your account was accessed. 53 |
54 |
55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/templates/email_templates/new_user_alert.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | New User Signup Notification 7 | 44 | 45 | 46 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/templates/email_templates/new_user_create.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | New User Signup Notification 7 | 44 | 45 | 46 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/templates/email_templates/notification_alert.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Notification Settings Changed 8 | 50 | 51 | 52 | 53 |
54 |
55 | Notification Settings Changed 56 |
57 |
58 | Hello,

59 | Your notification settings have been updated.

60 | {% if notifications_enabled %} 61 | You will now receive alerts for updates and changes. 62 | {% else %} 63 | You will no longer receive alerts. 64 | {% endif %}

65 | The changes were made by {{ current_user }} on {{ current_time }}. 66 |
67 | 71 |
72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /src/templates/email_templates/welcome.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Signup Successful 8 | 39 | 40 | 41 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/templates/error/400.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Bad Request{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | 7 | {% block content %} 8 |
9 |
10 |
11 |

400

12 |

The request could not be understood by the server.

13 | Go Back Home 14 |
15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /src/templates/error/403.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Permission Denied{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | 7 | {% block content %} 8 | {% include 'ext/message.html' %} 9 |
10 |
11 |
🚫
12 |

Permission Denied

13 |

Oops! You don't have permission to access this page.

14 | Go Back Home 15 |
16 |
17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /src/templates/error/404.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Page Not Found{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | 7 | {% block content %} 8 |
9 |
10 |
🙁
11 |

404

12 |

Oops! The page you are looking for does not exist.

13 | Go Back Home 14 |
15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /src/templates/error/405.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Method Not Allowed{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | 7 | {% block content %} 8 |
9 |
10 |
🚫
11 |

405

12 |

Sorry, the method is not allowed on this page.

13 | Go Back Home 14 |
15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /src/templates/error/500.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Internal Server Error{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | 7 | {% block content %} 8 |
9 |
10 |
11 |

500

12 |

Oops! Something went wrong on our end.

13 | Go Back Home 14 |
15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /src/templates/error/502.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Bad Gateway{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | 7 | {% block content %} 8 |
9 |
10 |
11 |

502

12 |

Bad gateway. Please try again later.

13 | Go Back Home 14 |
15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /src/templates/error/503.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Service Unavailable{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | 7 | {% block content %} 8 |
9 |
10 |
💬
11 |

503

12 |

Service is temporarily unavailable. Please check back soon.

13 | Go Back Home 14 |
15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /src/templates/error/speedtest_error.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %}{% block title %}Speedtest error{% endblock %}{% block extra_head %}{% endblock %}{% block content %}
Speed Test Failed
{{error}}
Retry
{% endblock %} -------------------------------------------------------------------------------- /src/templates/ext/footer.html: -------------------------------------------------------------------------------- 1 | 8 | 12 | -------------------------------------------------------------------------------- /src/templates/ext/header.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/templates/ext/message.html: -------------------------------------------------------------------------------- 1 | {% with messages=get_flashed_messages(with_categories=true) %}{% if messages %}
{% for category, 2 | message in messages %} {% endfor %}
{% 3 | endif %}{% endwith %} 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/templates/info_pages/cpu_info.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %}{% block title %}CPU Usage Details{% endblock %} 2 | {% block extra_head %} 3 | 4 | 5 | 6 | 7 | {% endblock %} 8 | {% block content %} 9 | {% include 'card_comp/selector/refresh_button.html' %} 10 |

CPU 11 | Details 12 |

13 |
14 |
15 |
16 | {% include 'card_comp/cpu/frequency.html' %} 17 |
18 |
19 | {% include 'card_comp/cpu/usages.html' %} 20 |
21 |
22 | {% include 'card_comp/cpu/current_temp.html' %} 23 |
24 |
25 | {% include 'card_comp/cpu/core.html' %} 26 |
27 |
28 | {% include 'card_comp/cpu/highest_temp.html' %} 29 |
30 |
31 |
32 | {% endblock %} 33 | {% block extra_scripts %} 34 | 35 | 36 | {% endblock %} -------------------------------------------------------------------------------- /src/templates/info_pages/disk_info.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %}{% block title %}Disk Usage Details{% endblock %} 2 | {% block extra_head %} 3 | 4 | 5 | 6 | 7 | {% endblock %} 8 | {% block content %} 9 | {% include 'card_comp/selector/refresh_button.html' %}

Disk 10 | Usage Details

11 |
12 |
{% include 'card_comp/disk/usage.html' %}
13 | 14 |
{% include 'card_comp/disk/total.html' %}
15 | 16 |
{% include 'card_comp/disk/used.html' %}
17 | 18 |
{% include 'card_comp/disk/free.html' %}
19 | 20 |
21 | {% endblock %} 22 | {% block extra_scripts %} 23 | 24 | 25 | {% endblock %} -------------------------------------------------------------------------------- /src/templates/info_pages/memory_info.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %}{% block title %}Memory Usage Details{% endblock %} 2 | {% block extra_head %} 3 | 4 | 5 | 6 | {% endblock %} 7 | {% block content %} 8 | {% include 'card_comp/selector/refresh_button.html' %} 9 |

Memory 10 | Usage Details

11 |
12 |
13 | {% include 'card_comp/memory/usage.html' %} 14 |
15 | 16 |
17 | {% include 'card_comp/memory/used.html' %} 18 |
19 |
20 | {% include 'card_comp/memory/dashboard_memory.html' %} 21 |
22 |
23 | {% include 'card_comp/memory/swap_total.html' %} 24 |
25 |
26 | {% include 'card_comp/memory/swap_used.html' %} 27 |
28 |
29 | {% include 'card_comp/memory/swap_free.html' %} 30 |
31 |
32 | {% endblock %} 33 | {% block extra_scripts %} 34 | 35 | 36 | {% endblock %} -------------------------------------------------------------------------------- /src/templates/info_pages/network_info.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %}{% block title %}Network Statistics - {{ title }}{% endblock %} 2 | {% block extra_head %} 3 | 4 | {% endblock %} 5 | {% block content %} 6 | {% include 'card_comp/selector/refresh_button.html' %} 7 |

8 | Network Statistics

9 |
10 |
11 | {% include 'card_comp/network/packets_sent.html' %} 12 |
13 |
14 | {% include 'card_comp/network/packets_received.html' %} 15 |
16 |
17 | {% include 'card_comp/network/ipv4_ip.html' %} 18 |
19 |
20 | {% include 'card_comp/network/ipv6_ip.html' %} 21 |
22 |
23 | {% endblock %} 24 | {% block extra_scripts %} 25 | 26 | {% endblock %} -------------------------------------------------------------------------------- /src/templates/info_pages/os_info.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}OS Level Information{% endblock %} 3 | {% block extra_head %} 4 | 5 | 6 | {% endblock %} 7 | {% block content %} 8 |
9 |

OS Level Information

10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
AttributeValue
Kernel Version{{ os_info.kernel_version }}
Operating System{{ os_info.operating_system }}
OS Codename{{ os_info.os_codename }}
OS Full Name{{ os_info.os_full_name }}
OS Name{{ os_info.os_name }}
OS Version{{ os_info.os_version }}
44 |
45 | {% endblock %} 46 | -------------------------------------------------------------------------------- /src/templates/network/dashboard_network.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Prometheus Active Targets{% endblock %} 3 | 4 | {% block extra_head %} 5 | 6 | {% endblock %} 7 | {% block content %} 8 |
9 |

SystemGuard Active Targets

10 | {% include 'ext/message.html' %} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
GroupInstanceHealthLast ScrapeLast ErrorScrape URLScrape Duration (s)Scrape IntervalGo to Dashboard
29 |
30 | {% endblock %} 31 | {% block extra_scripts %} 32 | 33 | {% endblock %} -------------------------------------------------------------------------------- /src/templates/other/smtp_config.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Update Email & Password{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | {% block content %} 7 |
8 |

SMTP Email Configuration

9 | {% include 'ext/message.html' %} 10 |
11 | 12 |
13 | 14 | 15 |
16 |
17 | 18 | 19 |
20 |
21 | 22 | 23 |
24 |
25 | 26 | 27 |
28 |
29 | 30 | 31 |
32 | 33 | 34 |
35 |
36 | {% endblock %} 37 | -------------------------------------------------------------------------------- /src/templates/other/speedtest_result.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %}{% block title %}Speed Test Result{% endblock %}{% block content %}
2 |
3 |
4 |
5 |
6 |

Speed Test Result

{% if speedtest_result %}
    8 |
  • Download 9 | Speed:{{ speedtest_result.download_speed}}
  • 10 |
  • Upload 11 | Speed:{{ speedtest_result.upload_speed}}
  • 12 |
  • 13 | Ping:{{ speedtest_result.ping}}
  • 14 |
  • 15 | Source:{{ source}}
  • {% if source=="Database" %}
  • Cooldown 17 | time:{{ remaining_time_for_next_test}} mins
  • {% endif %} 18 |
{% else %} {% endif %} 21 |
22 |
23 |
24 |
25 |
{% endblock %} -------------------------------------------------------------------------------- /src/templates/other/terminal.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Update Email & Password{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | {% block content %} 7 |
8 |
9 | 10 | 11 |
12 | 13 | 14 | {% endblock %} 15 | {% block extra_scripts %} 16 | 17 | {% endblock %} -------------------------------------------------------------------------------- /src/templates/ping/edit_website.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | 3 | {% block title %}Edit Website{% endblock %} 4 | 5 | {% block extra_head %} 6 | 7 | {% endblock %} 8 | 9 | {% block content %} 10 |
11 |

Update Website Details

12 |
13 | 14 |
15 | 16 |
17 | 18 | 19 |
20 |
21 | 22 | 23 |
24 |
25 | 26 | 27 |
28 |
29 | 30 | 31 |
32 | 33 |
34 |
35 | Back to Website List 36 |
37 | {% endblock %} 38 | -------------------------------------------------------------------------------- /src/templates/prometheus/external_monitoring.html: -------------------------------------------------------------------------------- 1 | {% extends "base/base.html" %} 2 | {% block title %}External Monitoring{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | {% block content %} 7 | 8 |
9 |

External Monitoring

10 | {% include 'ext/message.html' %} 11 |
12 |
13 |
14 |
15 | 16 | 17 | 18 |
19 | 20 |
21 |
22 |
23 |
24 | 25 | {% if data %} 26 |
27 |
Monitoring File Paths
28 | {% for item in data %} 29 |
30 |
31 | {{ item.file_path }} 32 |
33 | 34 | 35 |
36 |
37 |
38 | {% endfor %} 39 |
40 | {% endif %} 41 |
42 | 43 | {% endblock %} 44 | -------------------------------------------------------------------------------- /src/templates/settings/general_settings.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}General Settings{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | {% block content %} 7 |
8 |

General Settings

9 | 10 |
11 | 12 | {% include 'ext/message.html' %} 13 | 14 |
15 | 16 | 21 |
22 | 23 |
24 | 25 | 26 |
27 |
28 | 29 | 30 |
31 |
32 | 33 | 34 |
35 | 36 | 37 |
38 |
39 | {% endblock %} 40 | -------------------------------------------------------------------------------- /src/templates/settings/user_settings.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}Speedtest Settings{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | {% block content %} 7 |
8 |

User Settings

9 | 10 |
11 | 12 | {% include 'ext/message.html' %} 13 |
14 | 15 | 16 |
17 | 18 |
19 | 20 | 21 |
22 | 23 |
24 | 25 | 26 |
27 | 28 | 29 |
30 |
31 | {% endblock %} 32 | -------------------------------------------------------------------------------- /src/templates/users/change_password.html: -------------------------------------------------------------------------------- 1 | {% extends "base/base.html" %} 2 | {% block extra_head %} 3 | 4 | 5 | {% endblock %} 6 | {% block content %} 7 |
8 |

Change Password

9 | 12 | 13 | {% include 'ext/message.html' %} 14 | 15 |
16 | 17 |
18 | 19 | 20 |
21 | 22 |
23 | 24 | 25 |
26 | 27 |
28 | 29 | 30 |
31 | 32 | 33 |
34 |
35 | {% endblock %} 36 | -------------------------------------------------------------------------------- /src/templates/users/view_users.html: -------------------------------------------------------------------------------- 1 | {% extends 'base/base.html' %} 2 | {% block title %}View Users{% endblock %} 3 | {% block extra_head %} 4 | 5 | {% endblock %} 6 | {% block content %} 7 |
8 |

{{ title }} User Management

9 | 10 | Add New User 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | {% for user in users %} 25 | 26 | 27 | 28 | 29 | 30 | 31 | 38 | 39 | {% endfor %} 40 | 41 |
UsernameEmailUser LevelProfessionEmail AlertsActions
{{ user.username }}{{ user.email }}{{ user.user_level }}{{ user.profession }}{{ 'Yes' if user.receive_email_alerts else 'No' }} 32 | Edit 33 |
34 | 35 | 36 |
37 |
42 |
43 | {% endblock %} 44 | 45 | 46 | --------------------------------------------------------------------------------