Compare commits

..

19 commits
v2 ... main

Author SHA1 Message Date
Masu Baumgartner 39a1bdeb5d
Merge pull request #373 from Moonlight-Panel/v1_FixWingsContentLenght
Fix Content-Lenght for wings
2024-04-01 12:46:30 +02:00
Masu Baumgartner 18f107e485 A possible hotfix 2024-04-01 10:45:01 +00:00
Masu Baumgartner b56b94041f
Update README.md 2024-03-04 11:02:32 +01:00
Marcel Baumgartner 1a3b339983
Merge pull request #369 from NaysKutzu/patch-1
Update README.md
2024-02-09 14:22:39 +01:00
NaysKutzu 106af71c17
Update README.md
Update the logo because it won't be displayed due to your captcha on the page
2024-02-09 14:20:46 +01:00
Marcel Baumgartner cb1da9f5cd
Removed old license 2024-02-06 21:38:33 +01:00
Marcel Baumgartner 743b0b1c1b
Updated license 2024-02-06 21:37:32 +01:00
Marcel Baumgartner 8fe695f0cf
Merge pull request #367 from gOOvER/issuetemplates
added issue templates
2024-02-03 09:09:09 +01:00
Marcel Baumgartner 344ea046f2
Merge pull request #366 from gOOvER/dependabot
added dependabot.yml to autocheck action updates
2024-02-03 09:08:57 +01:00
Marcel Baumgartner 73a014500d
Merge pull request #365 from gOOvER/updateworkflow
update workflow files to latest releases
2024-02-03 09:08:38 +01:00
gOOvER d3f8ba5434 added issue templates 2024-02-03 08:44:05 +01:00
gOOvER c068679f9b added dependabot.yml to autocheck action updates 2024-02-03 08:27:36 +01:00
gOOvER 9dfba1e6c4 update workflow files to latest releases 2024-02-03 08:24:07 +01:00
Marcel Baumgartner 27f9ca551c
Create FUNDING.yml 2024-01-31 10:35:55 +01:00
Marcel Baumgartner 4d69e8bacb
Merge pull request #361 from Dannyx1604/patch-1
Update README.md (grammar check)
2024-01-25 21:43:00 +01:00
Dannyx ed2d33c69b
Update README.md (grammar check) 2024-01-25 21:39:48 +01:00
Marcel Baumgartner d880189f2b
Hotfix for WingsServerConverter 2024-01-12 19:45:18 +01:00
Marcel Baumgartner 9221a66597
Merge pull request #324 from Moonlight-Panel/FixLetsEncrypt
Added additional logs for lets encrypt certificates
2023-10-13 23:02:45 +02:00
Marcel Baumgartner e1c4f8a2a9
Added additional logs for lets encrypt certificates 2023-10-13 23:02:23 +02:00
1368 changed files with 146683 additions and 51977 deletions

View file

@ -0,0 +1,20 @@
{
"name": "C# (.NET)",
"image": "mcr.microsoft.com/devcontainers/dotnet:0-6.0",
"customizations": {
"vscode": {
"settings": {},
"extensions": [
"streetsidesoftware.code-spell-checker"
]
}
},
"portsAttributes": {
"5118": {
"label": "Moonlight",
"onAutoForward": "notify"
}
}
}

View file

@ -1,4 +1,5 @@
**/.dockerignore
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
@ -7,7 +8,6 @@
**/.toolstarget
**/.vs
**/.vscode
**/.idea
**/*.*proj.user
**/*.dbmdl
**/*.jfm

8
.gitattributes vendored
View file

@ -1,2 +1,10 @@
# Auto detect text files and perform LF normalization
* text=auto
Moonlight/wwwroot/** linguist-vendored
Moonlight/wwwroot/assets/js/scripts.bundle.js linguist-vendored
Moonlight/wwwroot/assets/js/widgets.bundle.js linguist-vendored
Moonlight/wwwroot/assets/js/theme.js linguist-vendored
Moonlight/wwwroot/assets/css/boxicons.min.css linguist-vendored
Moonlight/wwwroot/assets/css/style.bundle.css linguist-vendored
Moonlight/wwwroot/assets/plugins/** linguist-vendored
Moonlight/wwwroot/assets/fonts/** linguist-vendored

View file

@ -33,7 +33,7 @@ body:
attributes:
label: Panel Version
description: Version number of your Panel (latest is not a version)
placeholder: v2 EA
placeholder: 1.4.0
validations:
required: true
@ -42,7 +42,16 @@ body:
attributes:
label: Daemon Version
description: Version number of your Daemon (latest is not a version)
placeholder: v2 EA
placeholder: 1.4.2
validations:
required: true
- type: input
id: wings-version
attributes:
label: Wings Version
description: Version number of your Wings (latest is not a version)
placeholder: 1.4.2
validations:
required: true

12
.github/dependabot.yml vendored Normal file
View file

@ -0,0 +1,12 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
# Maintain Github workflows
- package-ecosystem: "github-actions"
directory: "/" # Must be set to / although they're located in .github/workflows
schedule:
interval: "daily"

View file

@ -0,0 +1,27 @@
name: Canary Docker Build
on:
workflow_dispatch:
pull_request:
types:
- closed
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login into docker hub
run: docker login -u ${{ secrets.DOCKER_USER }} -p ${{ secrets.DOCKER_PW }}
- name: Build and Push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Moonlight/Dockerfile
push: true
tags: moonlightpanel/moonlight:canary
platforms: linux/amd64,linux/arm64

View file

@ -0,0 +1,25 @@
name: Release Docker Build
on:
workflow_dispatch:
release:
types: [ published ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login into docker hub
run: docker login -u ${{ secrets.DOCKER_USER }} -p ${{ secrets.DOCKER_PW }}
- name: Build and Push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Moonlight/Dockerfile
push: true
tags: moonlightpanel/moonlight:beta
platforms: linux/amd64,linux/arm64

18
.github/workflows/test-docker-build.yml vendored Normal file
View file

@ -0,0 +1,18 @@
name: Test Build
on:
push:
branches: [ "main" ]
pull_request:
types:
- closed
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t moonlightpanel/moonlight:${{ github.sha }} -f Moonlight/Dockerfile .

431
.gitignore vendored
View file

@ -1,404 +1,45 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
 Common IntelliJ Platform excludes
# User specific
**/.idea/**/workspace.xml
**/.idea/**/tasks.xml
**/.idea/shelf/*
**/.idea/dictionaries
**/.idea/httpRequests/
# Sensitive or high-churn files
**/.idea/**/dataSources/
**/.idea/**/dataSources.ids
**/.idea/**/dataSources.xml
**/.idea/**/dataSources.local.xml
**/.idea/**/sqlDataSources.xml
**/.idea/**/dynamic.xml
# Rider
# Rider auto-generates .iml files, and contentModel.xml
**/.idea/**/*.iml
**/.idea/**/contentModel.xml
**/.idea/**/modules.xml
Moonlight/[Bb]in/
Moonlight/[Oo]bj/
Moonlight/_UpgradeReport_Files/
Moonlight/[Pp]ackages/
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
.vs/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
[Pp]ackages/
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
Thumbs.db
Desktop.ini
.DS_Store
.idea/.idea.Moonlight/.idea/discord.xml
storage/
.idea/.idea.Moonlight/.idea/dataSources.xml
Moonlight/wwwroot/css/theme.css
Moonlight/wwwroot/css/theme.css.map
.idea/.idea.Moonlight/.idea/discord.xml
Moonlight/publish.ps1
Moonlight/version

View file

@ -2,9 +2,9 @@
/shelf/
/workspace.xml
# Rider ignored files
/modules.xml
/contentModel.xml
/projectSettingsUpdater.xml
/modules.xml
/.idea.Moonlight.iml
# Editor-based HTTP Client requests
/httpRequests/

View file

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT_FILES" />
<option name="description" value="" />
<option name="theme" value="material" />
<option name="button1Title" value="" />
<option name="button1Url" value="" />
<option name="button2Title" value="" />
<option name="button2Url" value="" />
</component>
</project>

View file

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EfCoreCommonOptions">
<option name="migrationsToStartupProjects">
<map>
<entry key="16141d00-a997-4ba6-b0dc-af6f4712613a" value="16141d00-a997-4ba6-b0dc-af6f4712613a" />
</map>
</option>
<option name="solutionLevelOptions">
<map>
<entry key="migrationsProject" value="16141d00-a997-4ba6-b0dc-af6f4712613a" />
<entry key="startupProject" value="16141d00-a997-4ba6-b0dc-af6f4712613a" />
</map>
</option>
<option name="startupToMigrationsProjects">
<map>
<entry key="16141d00-a997-4ba6-b0dc-af6f4712613a" value="16141d00-a997-4ba6-b0dc-af6f4712613a" />
</map>
</option>
</component>
</project>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EfCoreDialogsState">
<option name="keyValueStorage">
<map>
<entry key="Common:16141d00-a997-4ba6-b0dc-af6f4712613a:dbContext" value="Moonlight.App.Database.DataContext" />
<entry key="Common:buildConfiguration" value="Debug" />
<entry key="Common:noBuild" value="false" />
<entry key="Common:outputFolder" value="App/Database/Migrations" />
<entry key="Common:useDefaultConnection" value="true" />
</map>
</option>
</component>
</project>

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MaterialThemeProjectNewConfig">
<option name="metadata">
<MTProjectMetadataState>
<option name="migrated" value="true" />
<option name="pristineConfig" value="false" />
<option name="userId" value="52a374ed:18c1029d858:-8000" />
<option name="version" value="8.13.2" />
</MTProjectMetadataState>
</option>
</component>
</project>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

6
.idea/vcs.xml Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View file

@ -0,0 +1,3 @@
<values>
<value name="mac.address" type="string">a6a05ab0b1614c08281b54fc3b3339170b0f57a5e246c20b7393333dfa28f8f1</value>
</values>

View file

@ -0,0 +1,3 @@
<values>
<value name="StillAlive" type="qword">133564417297189136</value>
</values>

View file

@ -0,0 +1,3 @@
<values>
<value name="MachineId" type="string">{A6A05AB0-B161-4C08-281B-54FC3B333917}</value>
</values>

35
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,35 @@
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md.
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/Moonlight/bin/Debug/net6.0/Moonlight.dll",
"args": [],
"cwd": "${workspaceFolder}/Moonlight",
"stopAtEntry": false,
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}

41
.vscode/tasks.json vendored Normal file
View file

@ -0,0 +1,41 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Moonlight.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/Moonlight.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"--project",
"${workspaceFolder}/Moonlight.sln"
],
"problemMatcher": "$msCompile"
}
]
}

View file

@ -1,6 +1,9 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moonlight", "Moonlight\Moonlight.csproj", "{B9AD26D2-AAA7-4C57-884D-5AACAA54D5B6}"
# Visual Studio Version 17
VisualStudioVersion = 17.2.32516.85
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moonlight", "Moonlight\Moonlight.csproj", "{16141D00-A997-4BA6-B0DC-AF6F4712613A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -8,11 +11,15 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B9AD26D2-AAA7-4C57-884D-5AACAA54D5B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B9AD26D2-AAA7-4C57-884D-5AACAA54D5B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B9AD26D2-AAA7-4C57-884D-5AACAA54D5B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B9AD26D2-AAA7-4C57-884D-5AACAA54D5B6}.Release|Any CPU.Build.0 = Release|Any CPU
{16141D00-A997-4BA6-B0DC-AF6F4712613A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{16141D00-A997-4BA6-B0DC-AF6F4712613A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{16141D00-A997-4BA6-B0DC-AF6F4712613A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{16141D00-A997-4BA6-B0DC-AF6F4712613A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9C904DEA-9663-4892-B3CA-5CD6E710648C}
EndGlobalSection
EndGlobal

View file

@ -1,26 +0,0 @@
@using Moonlight.Core.UI.Layouts
@using Moonlight.Core.Services
@inject FeatureService FeatureService
@{
var assemblies = FeatureService.UiContext.RouteAssemblies;
var firstAssembly = assemblies.First();
var additionalAssemblies = assemblies.Skip(1).ToArray();
}
<Router AppAssembly="@firstAssembly" AdditionalAssemblies="@additionalAssemblies">
<Found Context="routeData">
<CascadingValue TValue="Type" Name="TargetPageType" Value="@routeData.PageType">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
</CascadingValue>
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<IconAlert Title="Unknown page" Icon="bx-search">
The address you are trying to access is not associated with any page. To resume please go back or to the <a href="/">homepage</a>
</IconAlert>
</LayoutView>
</NotFound>
</Router>

View file

@ -0,0 +1,81 @@
using Newtonsoft.Json;
using RestSharp;
namespace Moonlight.App.ApiClients.CloudPanel;
public class CloudPanelApiHelper
{
private readonly RestClient Client;
public CloudPanelApiHelper()
{
Client = new();
}
public async Task Post(Database.Entities.CloudPanel cloudPanel, string resource, object? body)
{
var request = CreateRequest(cloudPanel, resource);
request.Method = Method.Post;
if(body != null)
request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody);
var response = await Client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new CloudPanelException(
$"An error occured: ({response.StatusCode}) {response.Content}",
(int)response.StatusCode
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
}
public async Task Delete(Database.Entities.CloudPanel cloudPanel, string resource, object? body)
{
var request = CreateRequest(cloudPanel, resource);
request.Method = Method.Delete;
if(body != null)
request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody);
var response = await Client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new CloudPanelException(
$"An error occured: ({response.StatusCode}) {response.Content}",
(int)response.StatusCode
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
}
private RestRequest CreateRequest(Database.Entities.CloudPanel cloudPanel, string resource)
{
var url = $"{cloudPanel.ApiUrl}/" + resource;
var request = new RestRequest(url);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Accept", "application/json");
request.AddHeader("Authorization", "Bearer " + cloudPanel.ApiKey);
return request;
}
}

View file

@ -0,0 +1,32 @@
using System.Runtime.Serialization;
namespace Moonlight.App.ApiClients.CloudPanel;
[Serializable]
public class CloudPanelException : Exception
{
public int StatusCode { get; set; }
public CloudPanelException()
{
}
public CloudPanelException(string message, int statusCode) : base(message)
{
StatusCode = statusCode;
}
public CloudPanelException(string message) : base(message)
{
}
public CloudPanelException(string message, Exception inner) : base(message, inner)
{
}
protected CloudPanelException(
SerializationInfo info,
StreamingContext context) : base(info, context)
{
}
}

View file

@ -0,0 +1,18 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.CloudPanel.Requests;
public class AddDatabase
{
[JsonProperty("domainName")]
public string DomainName { get; set; }
[JsonProperty("databaseName")]
public string DatabaseName { get; set; }
[JsonProperty("databaseUserName")]
public string DatabaseUserName { get; set; }
[JsonProperty("databaseUserPassword")]
public string DatabaseUserPassword { get; set; }
}

View file

@ -0,0 +1,16 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.CloudPanel.Requests;
public class AddPhpSite
{
[JsonProperty("domainName")] public string DomainName { get; set; } = "";
[JsonProperty("siteUser")] public string SiteUser { get; set; } = "";
[JsonProperty("siteUserPassword")] public string SiteUserPassword { get; set; } = "";
[JsonProperty("vHostTemplate")] public string VHostTemplate { get; set; } = "";
[JsonProperty("phpVersion")] public string PhpVersion { get; set; } = "";
}

View file

@ -0,0 +1,9 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.CloudPanel.Requests;
public class InstallLetsEncrypt
{
[JsonProperty("domainName")]
public string DomainName { get; set; }
}

View file

@ -0,0 +1,106 @@
using Moonlight.App.Database.Entities;
using Newtonsoft.Json;
using RestSharp;
namespace Moonlight.App.ApiClients.Daemon;
public class DaemonApiHelper
{
private readonly RestClient Client;
public DaemonApiHelper()
{
Client = new();
}
public async Task<T> Get<T>(Node node, string resource)
{
var request = await CreateRequest(node, resource);
request.Method = Method.Get;
var response = await Client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new DaemonException(
$"An error occured: ({response.StatusCode}) {response.Content}",
(int)response.StatusCode
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
return JsonConvert.DeserializeObject<T>(response.Content!)!;
}
public async Task Post(Node node, string resource, object body)
{
var request = await CreateRequest(node, resource);
request.Method = Method.Post;
request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody);
var response = await Client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new DaemonException(
$"An error occured: ({response.StatusCode}) {response.Content}",
(int)response.StatusCode
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
}
public async Task Delete(Node node, string resource, object body)
{
var request = await CreateRequest(node, resource);
request.Method = Method.Delete;
request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody);
var response = await Client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new DaemonException(
$"An error occured: ({response.StatusCode}) {response.Content}",
(int)response.StatusCode
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
}
private Task<RestRequest> CreateRequest(Node node, string resource)
{
var url = $"http://{node.Fqdn}:{node.MoonlightDaemonPort}/";
RestRequest request = new(url + resource);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Accept", "application/json");
request.AddHeader("Authorization", node.Token);
return Task.FromResult(request);
}
}

View file

@ -0,0 +1,32 @@
using System.Runtime.Serialization;
namespace Moonlight.App.ApiClients.Daemon;
[Serializable]
public class DaemonException : Exception
{
public int StatusCode { get; set; }
public DaemonException()
{
}
public DaemonException(string message, int statusCode) : base(message)
{
StatusCode = statusCode;
}
public DaemonException(string message) : base(message)
{
}
public DaemonException(string message, Exception inner) : base(message, inner)
{
}
protected DaemonException(
SerializationInfo info,
StreamingContext context) : base(info, context)
{
}
}

View file

@ -0,0 +1,8 @@
namespace Moonlight.App.ApiClients.Daemon.Requests;
public class Mount
{
public string Server { get; set; } = "";
public string ServerPath { get; set; } = "";
public string Path { get; set; } = "";
}

View file

@ -0,0 +1,6 @@
namespace Moonlight.App.ApiClients.Daemon.Requests;
public class Unmount
{
public string Path { get; set; } = "";
}

View file

@ -0,0 +1,10 @@
namespace Moonlight.App.ApiClients.Daemon.Resources;
public class Container
{
public string Name { get; set; } = "";
public long Memory { get; set; }
public double Cpu { get; set; }
public long NetworkIn { get; set; }
public long NetworkOut { get; set; }
}

View file

@ -0,0 +1,7 @@
namespace Moonlight.App.ApiClients.Daemon.Resources;
public class CpuMetrics
{
public string CpuModel { get; set; } = "";
public double CpuUsage { get; set; }
}

View file

@ -0,0 +1,7 @@
namespace Moonlight.App.ApiClients.Daemon.Resources;
public class DiskMetrics
{
public long Used { get; set; }
public long Total { get; set; }
}

View file

@ -0,0 +1,6 @@
namespace Moonlight.App.ApiClients.Daemon.Resources;
public class DockerMetrics
{
public Container[] Containers { get; set; } = Array.Empty<Container>();
}

View file

@ -0,0 +1,7 @@
namespace Moonlight.App.ApiClients.Daemon.Resources;
public class MemoryMetrics
{
public long Used { get; set; }
public long Total { get; set; }
}

View file

@ -0,0 +1,7 @@
namespace Moonlight.App.ApiClients.Daemon.Resources;
public class SystemMetrics
{
public string OsName { get; set; } = "";
public long Uptime { get; set; }
}

View file

@ -0,0 +1,21 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Google.Requests;
public class GoogleOAuth2CodePayload
{
[JsonProperty("grant_type")]
public string GrantType { get; set; } = "authorization_code";
[JsonProperty("code")]
public string Code { get; set; }
[JsonProperty("client_id")]
public string ClientId { get; set; }
[JsonProperty("client_secret")]
public string ClientSecret { get; set; }
[JsonProperty("redirect_uri")]
public string RedirectUri { get; set; }
}

View file

@ -0,0 +1,48 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.IpLocate.Resources;
public class IpLocate
{
[JsonProperty("query")]
public string Query { get; set; }
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("country")]
public string Country { get; set; }
[JsonProperty("countryCode")]
public string CountryCode { get; set; }
[JsonProperty("region")]
public string Region { get; set; }
[JsonProperty("regionName")]
public string RegionName { get; set; }
[JsonProperty("city")]
public string City { get; set; }
[JsonProperty("zip")]
public string Zip { get; set; }
[JsonProperty("lat")]
public double Lat { get; set; }
[JsonProperty("lon")]
public double Lon { get; set; }
[JsonProperty("timezone")]
public string Timezone { get; set; }
[JsonProperty("isp")]
public string Isp { get; set; }
[JsonProperty("org")]
public string Org { get; set; }
[JsonProperty("as")]
public string As { get; set; }
}

View file

@ -0,0 +1,58 @@
using Newtonsoft.Json;
using RestSharp;
namespace Moonlight.App.ApiClients.Modrinth;
public class ModrinthApiHelper
{
private readonly RestClient Client;
public ModrinthApiHelper()
{
Client = new();
Client.AddDefaultParameter(
new HeaderParameter("User-Agent", "Moonlight-Panel/Moonlight (admin@endelon-hosting.de)")
);
}
public async Task<T> Get<T>(string resource)
{
var request = CreateRequest(resource);
request.Method = Method.Get;
var response = await Client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new ModrinthException(
$"An error occured: ({response.StatusCode}) {response.Content}",
(int)response.StatusCode
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
return JsonConvert.DeserializeObject<T>(response.Content!)!;
}
private RestRequest CreateRequest(string resource)
{
var url = "https://api.modrinth.com/v2/" + resource;
var request = new RestRequest(url)
{
Timeout = 300000
};
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Accept", "application/json");
return request;
}
}

View file

@ -0,0 +1,19 @@
namespace Moonlight.App.ApiClients.Modrinth;
public class ModrinthException : Exception
{
public int StatusCode { get; set; }
public ModrinthException()
{
}
public ModrinthException(string message, int statusCode) : base(message)
{
StatusCode = statusCode;
}
public ModrinthException(string message, Exception inner) : base(message, inner)
{
}
}

View file

@ -0,0 +1,14 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Modrinth.Resources;
public class Pagination
{
[JsonProperty("hits")] public Project[] Hits { get; set; }
[JsonProperty("offset")] public long Offset { get; set; }
[JsonProperty("limit")] public long Limit { get; set; }
[JsonProperty("total_hits")] public long TotalHits { get; set; }
}

View file

@ -0,0 +1,48 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Modrinth.Resources;
public class Project
{
[JsonProperty("project_id")] public string ProjectId { get; set; }
[JsonProperty("project_type")] public string ProjectType { get; set; }
[JsonProperty("slug")] public string Slug { get; set; }
[JsonProperty("author")] public string Author { get; set; }
[JsonProperty("title")] public string Title { get; set; }
[JsonProperty("description")] public string Description { get; set; }
[JsonProperty("categories")] public string[] Categories { get; set; }
[JsonProperty("display_categories")] public string[] DisplayCategories { get; set; }
[JsonProperty("versions")] public string[] Versions { get; set; }
[JsonProperty("downloads")] public long Downloads { get; set; }
[JsonProperty("follows")] public long Follows { get; set; }
[JsonProperty("icon_url")] public string IconUrl { get; set; }
[JsonProperty("date_created")] public DateTimeOffset DateCreated { get; set; }
[JsonProperty("date_modified")] public DateTimeOffset DateModified { get; set; }
[JsonProperty("latest_version")] public string LatestVersion { get; set; }
[JsonProperty("license")] public string License { get; set; }
[JsonProperty("client_side")] public string ClientSide { get; set; }
[JsonProperty("server_side")] public string ServerSide { get; set; }
[JsonProperty("gallery")] public Uri[] Gallery { get; set; }
[JsonProperty("featured_gallery")] public Uri FeaturedGallery { get; set; }
[JsonProperty("color")] public long? Color { get; set; }
}

View file

@ -0,0 +1,57 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Modrinth.Resources;
public class Version
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("version_number")]
public string VersionNumber { get; set; }
[JsonProperty("changelog")]
public string Changelog { get; set; }
[JsonProperty("dependencies")]
public object[] Dependencies { get; set; }
[JsonProperty("game_versions")]
public object[] GameVersions { get; set; }
[JsonProperty("version_type")]
public string VersionType { get; set; }
[JsonProperty("loaders")]
public object[] Loaders { get; set; }
[JsonProperty("featured")]
public bool Featured { get; set; }
[JsonProperty("status")]
public string Status { get; set; }
[JsonProperty("requested_status")]
public string RequestedStatus { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("project_id")]
public string ProjectId { get; set; }
[JsonProperty("author_id")]
public string AuthorId { get; set; }
[JsonProperty("date_published")]
public DateTime DatePublished { get; set; }
[JsonProperty("downloads")]
public long Downloads { get; set; }
[JsonProperty("changelog_url")]
public object ChangelogUrl { get; set; }
[JsonProperty("files")]
public VersionFile[] Files { get; set; }
}

View file

@ -0,0 +1,21 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Modrinth.Resources;
public class VersionFile
{
[JsonProperty("url")]
public Uri Url { get; set; }
[JsonProperty("filename")]
public string Filename { get; set; }
[JsonProperty("primary")]
public bool Primary { get; set; }
[JsonProperty("size")]
public long Size { get; set; }
[JsonProperty("file_type")]
public string FileType { get; set; }
}

View file

@ -0,0 +1,49 @@
using Moonlight.App.Exceptions;
using Newtonsoft.Json;
using RestSharp;
namespace Moonlight.App.ApiClients.Paper;
public class PaperApiHelper
{
private string ApiUrl { get; set; }
public PaperApiHelper()
{
ApiUrl = "https://api.papermc.io/v2/projects/";
}
public async Task<T> Get<T>(string url)
{
RestClient client = new();
string requrl = "NONSET";
if (ApiUrl.EndsWith("/"))
requrl = ApiUrl + url;
else
requrl = ApiUrl + "/" + url;
RestRequest request = new(requrl, Method.Get);
request.AddHeader("Content-Type", "application/json");
var response = await client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new PaperException(
$"An error occured: ({response.StatusCode}) {response.Content}"
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
return JsonConvert.DeserializeObject<T>(response.Content!)!;
}
}

View file

@ -0,0 +1,16 @@
namespace Moonlight.App.ApiClients.Paper;
public class PaperException : Exception
{
public PaperException()
{
}
public PaperException(string message) : base(message)
{
}
public PaperException(string message, Exception inner) : base(message, inner)
{
}
}

View file

@ -0,0 +1,18 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Paper.Resources;
public class PaperBuilds
{
[JsonProperty("project_id")]
public string ProjectId { get; set; }
[JsonProperty("project_name")]
public string ProjectName { get; set; }
[JsonProperty("version")]
public string Version { get; set; }
[JsonProperty("builds")]
public List<string> Builds { get; set; }
}

View file

@ -0,0 +1,18 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Paper.Resources;
public class PaperVersions
{
[JsonProperty("project_id")]
public string ProjectId { get; set; }
[JsonProperty("project_name")]
public string ProjectName { get; set; }
[JsonProperty("version_groups")]
public List<string> VersionGroups { get; set; }
[JsonProperty("versions")]
public List<string> Versions { get; set; }
}

View file

@ -0,0 +1,11 @@
namespace Moonlight.App.ApiClients.Telemetry.Requests;
public class TelemetryData
{
public string AppUrl { get; set; } = "";
public int Servers { get; set; }
public int Nodes { get; set; }
public int Users { get; set; }
public int Databases { get; set; }
public int Webspaces { get; set; }
}

View file

@ -0,0 +1,52 @@
using Newtonsoft.Json;
using RestSharp;
namespace Moonlight.App.ApiClients.Telemetry;
public class TelemetryApiHelper
{
private readonly RestClient Client;
public TelemetryApiHelper()
{
Client = new();
}
public async Task Post(string resource, object? body)
{
var request = CreateRequest(resource);
request.Method = Method.Post;
request.AddParameter("application/json", JsonConvert.SerializeObject(body), ParameterType.RequestBody);
var response = await Client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new TelemetryException(
$"An error occured: ({response.StatusCode}) {response.Content}",
(int)response.StatusCode
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
}
private RestRequest CreateRequest(string resource)
{
var url = "https://telemetry.moonlightpanel.xyz/" + resource;
var request = new RestRequest(url)
{
Timeout = 3000000
};
return request;
}
}

View file

@ -0,0 +1,32 @@
using System.Runtime.Serialization;
namespace Moonlight.App.ApiClients.Telemetry;
[Serializable]
public class TelemetryException : Exception
{
public int StatusCode { get; set; }
public TelemetryException()
{
}
public TelemetryException(string message, int statusCode) : base(message)
{
StatusCode = statusCode;
}
public TelemetryException(string message) : base(message)
{
}
public TelemetryException(string message, Exception inner) : base(message, inner)
{
}
protected TelemetryException(
SerializationInfo info,
StreamingContext context) : base(info, context)
{
}
}

View file

@ -0,0 +1,9 @@
namespace Moonlight.App.ApiClients.Wings;
public enum PowerSignal
{
Start,
Stop,
Kill,
Restart
}

View file

@ -0,0 +1,12 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Wings.Requests;
public class CompressFiles
{
[JsonProperty("root")]
public string Root { get; set; }
[JsonProperty("files")]
public string[] Files { get; set; }
}

View file

@ -0,0 +1,15 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Wings.Requests;
public class CreateBackup
{
[JsonProperty("adapter")]
public string Adapter { get; set; }
[JsonProperty("uuid")]
public Guid Uuid { get; set; }
[JsonProperty("ignore")]
public string Ignore { get; set; }
}

View file

@ -0,0 +1,12 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Wings.Requests;
public class CreateDirectory
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("path")]
public string Path { get; set; }
}

View file

@ -0,0 +1,12 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Wings.Requests;
public class CreateServer
{
[JsonProperty("uuid")]
public Guid Uuid { get; set; }
[JsonProperty("start_on_completion")]
public bool StartOnCompletion { get; set; }
}

View file

@ -0,0 +1,12 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Wings.Requests;
public class DecompressFile
{
[JsonProperty("root")]
public string Root { get; set; }
[JsonProperty("file")]
public string File { get; set; }
}

View file

@ -0,0 +1,11 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Wings.Requests;
public class DeleteFiles
{
[JsonProperty("root")]
public string Root { get; set; }
[JsonProperty("files")] public List<string> Files { get; set; } = new();
}

View file

@ -0,0 +1,20 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Wings.Requests;
public class RenameFiles
{
[JsonProperty("root")]
public string Root { get; set; }
[JsonProperty("files")] public RenameFilesData[] Files { get; set; }
}
public class RenameFilesData
{
[JsonProperty("from")]
public string From { get; set; }
[JsonProperty("to")]
public string To { get; set; }
}

View file

@ -0,0 +1,12 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Wings.Requests;
public class RestoreBackup
{
[JsonProperty("adapter")]
public string Adapter { get; set; }
[JsonProperty("truncate_directory")] public bool TruncateDirectory { get; set; } = false;
[JsonProperty("download_url")] public string DownloadUrl { get; set; } = "";
}

View file

@ -0,0 +1,9 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Wings.Requests;
public class ServerPower
{
[JsonProperty("action")]
public string Action { get; set; }
}

View file

@ -0,0 +1,30 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Wings.Resources;
public class ListDirectory
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("created")]
public DateTimeOffset Created { get; set; }
[JsonProperty("modified")]
public DateTimeOffset Modified { get; set; }
[JsonProperty("size")]
public long Size { get; set; }
[JsonProperty("directory")]
public bool Directory { get; set; }
[JsonProperty("file")]
public bool File { get; set; }
[JsonProperty("symlink")]
public bool Symlink { get; set; }
[JsonProperty("mime")]
public string Mime { get; set; }
}

View file

@ -0,0 +1,48 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Wings.Resources;
public class ServerDetails
{
[JsonProperty("state")]
public string State { get; set; }
[JsonProperty("is_suspended")]
public bool IsSuspended { get; set; }
[JsonProperty("utilization")]
public ServerDetailsUtilization Utilization { get; set; }
public class ServerDetailsUtilization
{
[JsonProperty("memory_bytes")]
public long MemoryBytes { get; set; }
[JsonProperty("memory_limit_bytes")]
public long MemoryLimitBytes { get; set; }
[JsonProperty("cpu_absolute")]
public double CpuAbsolute { get; set; }
[JsonProperty("network")]
public ServerDetailsNetwork Network { get; set; }
[JsonProperty("uptime")]
public long Uptime { get; set; }
[JsonProperty("state")]
public string State { get; set; }
[JsonProperty("disk_bytes")]
public long DiskBytes { get; set; }
}
public class ServerDetailsNetwork
{
[JsonProperty("rx_bytes")]
public long RxBytes { get; set; }
[JsonProperty("tx_bytes")]
public long TxBytes { get; set; }
}
}

View file

@ -0,0 +1,21 @@
using Newtonsoft.Json;
namespace Moonlight.App.ApiClients.Wings.Resources;
public class SystemStatus
{
[JsonProperty("architecture")]
public string Architecture { get; set; }
[JsonProperty("cpu_count")]
public long CpuCount { get; set; }
[JsonProperty("kernel_version")]
public string KernelVersion { get; set; }
[JsonProperty("os")]
public string Os { get; set; }
[JsonProperty("version")]
public string Version { get; set; }
}

View file

@ -0,0 +1,221 @@
using Moonlight.App.Database.Entities;
using Moonlight.App.Exceptions;
using Newtonsoft.Json;
using RestSharp;
namespace Moonlight.App.ApiClients.Wings;
public class WingsApiHelper
{
private readonly RestClient Client;
public WingsApiHelper()
{
Client = new();
}
public async Task<T> Get<T>(Node node, string resource)
{
var request = CreateRequest(node, resource);
request.Method = Method.Get;
var response = await Client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new WingsException(
$"An error occured: ({response.StatusCode}) {response.Content}",
(int)response.StatusCode
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
return JsonConvert.DeserializeObject<T>(response.Content!)!;
}
public async Task<string> GetRaw(Node node, string resource)
{
var request = CreateRequest(node, resource);
request.Method = Method.Get;
var response = await Client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new WingsException(
$"An error occured: ({response.StatusCode}) {response.Content}",
(int)response.StatusCode
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
return response.Content!;
}
public async Task<T> Post<T>(Node node, string resource, object? body)
{
var request = CreateRequest(node, resource);
request.Method = Method.Post;
request.AddParameter("text/plain",
JsonConvert.SerializeObject(body),
ParameterType.RequestBody
);
var response = await Client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new WingsException(
$"An error occured: ({response.StatusCode}) {response.Content}",
(int)response.StatusCode
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
return JsonConvert.DeserializeObject<T>(response.Content!)!;
}
public async Task Post(Node node, string resource, object? body)
{
var request = CreateRequest(node, resource);
request.Method = Method.Post;
if(body != null)
request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody);
var response = await Client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new WingsException(
$"An error occured: ({response.StatusCode}) {response.Content}",
(int)response.StatusCode
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
}
public async Task PostRaw(Node node, string resource, object body)
{
var request = CreateRequest(node, resource);
request.Method = Method.Post;
request.AddParameter("text/plain", body, ParameterType.RequestBody);
var response = await Client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new WingsException(
$"An error occured: ({response.StatusCode}) {response.Content}",
(int)response.StatusCode
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
}
public async Task Delete(Node node, string resource, object? body)
{
var request = CreateRequest(node, resource);
request.Method = Method.Delete;
if(body != null)
request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody);
var response = await Client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new WingsException(
$"An error occured: ({response.StatusCode}) {response.Content}",
(int)response.StatusCode
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
}
public async Task Put(Node node, string resource, object? body)
{
var request = CreateRequest(node, resource);
request.Method = Method.Put;
request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody);
var response = await Client.ExecuteAsync(request);
if (!response.IsSuccessful)
{
if (response.StatusCode != 0)
{
throw new WingsException(
$"An error occured: ({response.StatusCode}) {response.Content}",
(int)response.StatusCode
);
}
else
{
throw new Exception($"An internal error occured: {response.ErrorMessage}");
}
}
}
private RestRequest CreateRequest(Node node, string resource)
{
var url = (node.Ssl ? "https" : "http") + $"://{node.Fqdn}:{node.HttpPort}/" + resource;
var request = new RestRequest(url)
{
Timeout = 300000
};
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Accept", "application/json");
request.AddHeader("Authorization", "Bearer " + node.Token);
return request;
}
}

View file

@ -0,0 +1,32 @@
using System.Runtime.Serialization;
namespace Moonlight.App.ApiClients.Wings;
[Serializable]
public class WingsException : Exception
{
public int StatusCode { get; set; }
public WingsException()
{
}
public WingsException(string message, int statusCode) : base(message)
{
StatusCode = statusCode;
}
public WingsException(string message) : base(message)
{
}
public WingsException(string message, Exception inner) : base(message, inner)
{
}
protected WingsException(
SerializationInfo info,
StreamingContext context) : base(info, context)
{
}
}

View file

@ -0,0 +1,410 @@
using System.ComponentModel;
using Moonlight.App.Helpers;
namespace Moonlight.App.Configuration;
using System;
using Newtonsoft.Json;
public class ConfigV1
{
[JsonProperty("Moonlight")] public MoonlightData Moonlight { get; set; } = new();
public class MoonlightData
{
[JsonProperty("AppUrl")]
[Description("The url moonlight is accesible with from the internet")]
public string AppUrl { get; set; } = "http://your-moonlight-url-without-slash";
[JsonProperty("EnableLatencyCheck")]
[Description(
"This will enable a latency check for connections to moonlight. Users with an too high latency will be warned that moonlight might be buggy for them")]
public bool EnableLatencyCheck { get; set; } = true;
[JsonProperty("LatencyCheckThreshold")]
[Description("Specify the latency threshold which has to be reached in order to trigger the warning message")]
public int LatencyCheckThreshold { get; set; } = 1000;
[JsonProperty("LetsEncrypt")] public LetsEncrypt LetsEncrypt { get; set; } = new();
[JsonProperty("Auth")] public AuthData Auth { get; set; } = new();
[JsonProperty("Database")] public DatabaseData Database { get; set; } = new();
[JsonProperty("DiscordBotApi")] public DiscordBotApiData DiscordBotApi { get; set; } = new();
[JsonProperty("DiscordBot")] public DiscordBotData DiscordBot { get; set; } = new();
[JsonProperty("Domains")] public DomainsData Domains { get; set; } = new();
[JsonProperty("Html")] public HtmlData Html { get; set; } = new();
[JsonProperty("Marketing")] public MarketingData Marketing { get; set; } = new();
[JsonProperty("OAuth2")] public OAuth2Data OAuth2 { get; set; } = new();
[JsonProperty("Security")] public SecurityData Security { get; set; } = new();
[JsonProperty("Mail")] public MailData Mail { get; set; } = new();
[JsonProperty("Cleanup")] public CleanupData Cleanup { get; set; } = new();
[JsonProperty("DiscordNotifications")]
public DiscordNotificationsData DiscordNotifications { get; set; } = new();
[JsonProperty("Statistics")] public StatisticsData Statistics { get; set; } = new();
[JsonProperty("Rating")] public RatingData Rating { get; set; } = new();
[JsonProperty("SmartDeploy")] public SmartDeployData SmartDeploy { get; set; } = new();
[JsonProperty("Sentry")] public SentryData Sentry { get; set; } = new();
[JsonProperty("Stripe")] public StripeData Stripe { get; set; } = new();
[JsonProperty("Tickets")] public TicketsData Tickets { get; set; } = new();
}
public class LetsEncrypt
{
[JsonProperty("Enable")]
[Description("Enable automatic lets encrypt certificate issuing. This is a beta feature")]
public bool Enable { get; set; } = false;
[JsonProperty("ExpireEmail")]
[Description("Lets encrypt will send you an email upon certificate expiration to this address")]
public string ExpireEmail { get; set; } = "your@email.test";
[JsonProperty("CountryCode")]
[Description("Country code to use for generating the certificate")]
public string CountryCode { get; set; } = "DE";
[JsonProperty("State")]
[Description("State to use for generating the certificate")]
public string State { get; set; } = "Germany";
[JsonProperty("Locality")]
[Description("Locality to use for generating the certificate")]
public string Locality { get; set; } = "Bavaria";
[JsonProperty("Organization")]
[Description("Organization to use for generating the certificate")]
public string Organization { get; set; } = "Moonlight Panel";
}
public class TicketsData
{
[JsonProperty("WelcomeMessage")]
[Description("The message that will be sent when a user created a ticket")]
public string WelcomeMessage { get; set; } = "Welcome to the support";
}
public class StripeData
{
[JsonProperty("ApiKey")]
[Description(
"Put here your stripe api key if you add subscriptions. Currently the only billing option is stripe which is enabled by default and cannot be turned off. This feature is still experimental")]
public string ApiKey { get; set; } = "";
}
public class AuthData
{
[JsonProperty("DenyLogin")]
[Description("Prevent every new login")]
public bool DenyLogin { get; set; } = false;
[JsonProperty("DenyRegister")]
[Description("Prevent every new user to register")]
public bool DenyRegister { get; set; } = false;
[JsonProperty("CheckForBots")]
[Description("Check for bots when a user has been registered")]
public bool CheckForBots { get; set; } = true;
[JsonProperty("BlockLinuxUsers")]
[Description("Blocks linux users from registering")]
public bool BlockLinuxUsers { get; set; } = false;
}
public class CleanupData
{
[JsonProperty("Cpu")]
[Description("The maximum amount of cpu usage in percent a node is allowed to use before the cleanup starts")]
public long Cpu { get; set; } = 90;
[JsonProperty("Memory")]
[Description("The minumum amount of memory in megabytes avaliable before the cleanup starts")]
public long Memory { get; set; } = 8192;
[JsonProperty("Wait")]
[Description("The delay between every cleanup check in minutes")]
public long Wait { get; set; } = 15;
[JsonProperty("Uptime")]
[Description("The maximum uptime of any server in hours before it the server restarted by the cleanup system")]
public long Uptime { get; set; } = 6;
[JsonProperty("Enable")]
[Description(
"The cleanup system provides a fair way for stopping unused servers and staying stable even with overallocation. A detailed explanation: docs.endelon-hosting.de/erklaerungen/cleanup")]
public bool Enable { get; set; } = false;
[JsonProperty("MinUptime")]
[Description("The minumum uptime of a server in minutes to prevent stopping servers which just started")]
public long MinUptime { get; set; } = 10;
}
public class DatabaseData
{
[JsonProperty("Database")] public string Database { get; set; } = "moonlight_db";
[JsonProperty("Host")] public string Host { get; set; } = "your.database.host";
[JsonProperty("Password")] [Blur] public string Password { get; set; } = "secret";
[JsonProperty("Port")] public long Port { get; set; } = 3306;
[JsonProperty("Username")] public string Username { get; set; } = "moonlight_user";
}
public class DiscordBotApiData
{
[JsonProperty("Enable")]
[Description("Enable the discord bot api. Currently only DatBot is using this api")]
public bool Enable { get; set; } = false;
[JsonProperty("Token")]
[Description("Specify the token the api client needs to provide")]
[Blur]
public string Token { get; set; } = Guid.NewGuid().ToString();
}
public class DiscordBotData
{
[JsonProperty("Enable")]
[Description("The discord bot can be used to allow customers to manage their servers via discord")]
public bool Enable { get; set; } = false;
[JsonProperty("Token")]
[Description("Your discord bot token goes here")]
[Blur]
public string Token { get; set; } = "discord token here";
[JsonProperty("PowerActions")]
[Description("Enable actions like starting and stopping servers")]
public bool PowerActions { get; set; } = false;
[JsonProperty("SendCommands")]
[Description("Allow users to send commands to their servers")]
public bool SendCommands { get; set; } = false;
}
public class DiscordNotificationsData
{
[JsonProperty("Enable")]
[Description(
"The discord notification system sends you a message everytime a event like a new support chat message is triggered with usefull data describing the event")]
public bool Enable { get; set; } = false;
[JsonProperty("WebHook")]
[Description("The discord webhook the notifications are being sent to")]
[Blur]
public string WebHook { get; set; } = "http://your-discord-webhook-url";
}
public class DomainsData
{
[JsonProperty("Enable")]
[Description("This enables the domain system")]
public bool Enable { get; set; } = false;
[JsonProperty("AccountId")]
[Description("This option specifies the cloudflare account id")]
public string AccountId { get; set; } = "cloudflare acc id";
[JsonProperty("Email")]
[Description("This specifies the cloudflare email to use for communicating with the cloudflare api")]
public string Email { get; set; } = "cloudflare@acc.email";
[JsonProperty("Key")]
[Description("Your cloudflare api key goes here")]
[Blur]
public string Key { get; set; } = "secret";
}
public class HtmlData
{
[JsonProperty("Headers")] public HeadersData Headers { get; set; } = new();
}
public class HeadersData
{
[JsonProperty("Color")]
[Description(
"This specifies the color of the embed generated by platforms like discord when someone posts a link to your moonlight instance")]
public string Color { get; set; } = "#4b27e8";
[JsonProperty("Description")]
[Description(
"This specifies the description text of the embed generated by platforms like discord when someone posts a link to your moonlight instance and can also help google to index your moonlight instance correctly")]
public string Description { get; set; } = "the next generation hosting panel";
[JsonProperty("Keywords")]
[Description(
"To help search engines like google to index your moonlight instance correctly you can specify keywords seperated by a comma here")]
public string Keywords { get; set; } = "moonlight";
[JsonProperty("Title")]
[Description(
"This specifies the title of the embed generated by platforms like discord when someone posts a link to your moonlight instance")]
public string Title { get; set; } = "Moonlight - endelon.link";
}
public class MailData
{
[JsonProperty("Email")] public string Email { get; set; } = "username@your.mail.host";
[JsonProperty("Server")] public string Server { get; set; } = "your.mail.host";
[JsonProperty("Password")] [Blur] public string Password { get; set; } = "secret";
[JsonProperty("Port")] public int Port { get; set; } = 465;
[JsonProperty("Ssl")] public bool Ssl { get; set; } = true;
}
public class MarketingData
{
[JsonProperty("BrandName")] public string BrandName { get; set; } = "Endelon Hosting";
[JsonProperty("Imprint")] public string Imprint { get; set; } = "https://your-site.xyz/imprint";
[JsonProperty("Privacy")] public string Privacy { get; set; } = "https://your-site.xyz/privacy";
[JsonProperty("About")] public string About { get; set; } = "https://your-site.xyz/about";
[JsonProperty("Website")] public string Website { get; set; } = "https://your-site.xyz";
}
public class OAuth2Data
{
[JsonProperty("OverrideUrl")]
[Description("This overrides the redirect url which would be typicaly the app url")]
public string OverrideUrl { get; set; } = "https://only-for-development.cases";
[JsonProperty("EnableOverrideUrl")]
[Description("This enables the url override")]
public bool EnableOverrideUrl { get; set; } = false;
[JsonProperty("Providers")]
public OAuth2ProviderData[] Providers { get; set; } = Array.Empty<OAuth2ProviderData>();
}
public class OAuth2ProviderData
{
[JsonProperty("Id")] public string Id { get; set; }
[JsonProperty("ClientId")] public string ClientId { get; set; }
[JsonProperty("ClientSecret")] [Blur] public string ClientSecret { get; set; }
}
public class RatingData
{
[JsonProperty("Enabled")]
[Description(
"The rating systems shows a user who is registered longer than the set amout of days a popup to rate this platform if he hasnt rated it before")]
public bool Enabled { get; set; } = false;
[JsonProperty("Url")]
[Description(
"This is the url a user who rated above a set limit is shown to rate you again. Its recommended to put your google or trustpilot rate link here")]
public string Url { get; set; } = "https://link-to-google-or-smth";
[JsonProperty("MinRating")]
[Description("The minimum star count on the rating ranging from 1 to 5")]
public int MinRating { get; set; } = 4;
[JsonProperty("DaysSince")]
[Description("The days a user has to be registered to even be able to get this popup")]
public int DaysSince { get; set; } = 5;
}
public class SecurityData
{
[JsonProperty("Token")]
[Description(
"This is the moonlight app token. It is used to encrypt and decrypt data and validate tokens and sessions")]
[Blur]
public string Token { get; set; } = Guid.NewGuid().ToString();
[JsonProperty("MalwareCheckOnStart")]
[Description(
"This option will enable the scanning for malware on every server before it has been started and if something has been found, the power action will be canceled")]
public bool MalwareCheckOnStart { get; set; } = true;
[JsonProperty("BlockIpDuration")]
[Description("The duration in minutes a ip will be blocked by the anti ddos system")]
public int BlockIpDuration { get; set; } = 15;
[JsonProperty("ReCaptcha")] public ReCaptchaData ReCaptcha { get; set; } = new();
[JsonProperty("BlockDatacenterIps")]
[Description(
"If this option is enabled, users with an ip from datacenters will not be able to access the panel")]
public bool BlockDatacenterIps { get; set; } = true;
[JsonProperty("AllowCloudflareIps")]
[Description("Allow cloudflare ips to bypass the datacenter ip check")]
public bool AllowCloudflareIps { get; set; } = false;
}
public class ReCaptchaData
{
[JsonProperty("Enable")]
[Description(
"Enables repatcha at places like the register page. For information how to get your recaptcha credentails go to google.com/recaptcha/about/")]
public bool Enable { get; set; } = false;
[JsonProperty("SiteKey")] [Blur] public string SiteKey { get; set; } = "recaptcha site key here";
[JsonProperty("SecretKey")] [Blur] public string SecretKey { get; set; } = "recaptcha secret here";
}
public class SentryData
{
[JsonProperty("Enable")]
[Description(
"Sentry is a way to monitor application crashes and performance issues in real time. Enable this option only if you set a sentry dsn")]
public bool Enable { get; set; } = false;
[JsonProperty("Dsn")]
[Description("The dsn is the key moonlight needs to communicate with your sentry instance")]
[Blur]
public string Dsn { get; set; } = "http://your-sentry-url-here";
}
public class SmartDeployData
{
[JsonProperty("Server")] public SmartDeployServerData Server { get; set; } = new();
}
public class SmartDeployServerData
{
[JsonProperty("EnableOverride")] public bool EnableOverride { get; set; } = false;
[JsonProperty("OverrideNode")] public long OverrideNode { get; set; } = 1;
}
public class StatisticsData
{
[JsonProperty("Enabled")] public bool Enabled { get; set; } = false;
[JsonProperty("Wait")] public long Wait { get; set; } = 15;
}
public class SellPassData
{
[JsonProperty("Enable")] public bool Enable { get; set; } = false;
[JsonProperty("Url")] public string Url { get; set; } = "https://not-implemented-yet";
}
}

View file

@ -0,0 +1,78 @@
using Microsoft.EntityFrameworkCore;
using Moonlight.App.Database.Entities;
using Moonlight.App.Database.Entities.Notification;
using Moonlight.App.Database.Interceptors;
using Moonlight.App.Services;
namespace Moonlight.App.Database;
public class DataContext : DbContext
{
private readonly ConfigService ConfigService;
public DataContext(ConfigService configService)
{
ConfigService = configService;
}
public DbSet<DockerImage> DockerImages { get; set; }
public DbSet<Image> Images { get; set; }
public DbSet<ImageVariable> ImageVariables { get; set; }
public DbSet<Node> Nodes { get; set; }
public DbSet<NodeAllocation> NodeAllocations { get; set; }
public DbSet<Server> Servers { get; set; }
public DbSet<ServerBackup> ServerBackups { get; set; }
public DbSet<ServerVariable> ServerVariables { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<LoadingMessage> LoadingMessages { get; set; }
public DbSet<SharedDomain> SharedDomains { get; set; }
public DbSet<Domain> Domains { get; set; }
public DbSet<Revoke> Revokes { get; set; }
public DbSet<NotificationClient> NotificationClients { get; set; }
public DbSet<NotificationAction> NotificationActions { get; set; }
public DbSet<DdosAttack> DdosAttacks { get; set; }
public DbSet<Subscription> Subscriptions { get; set; }
public DbSet<StatisticsData> Statistics { get; set; }
public DbSet<NewsEntry> NewsEntries { get; set; }
public DbSet<CloudPanel> CloudPanels { get; set; }
public DbSet<MySqlDatabase> Databases { get; set; }
public DbSet<WebSpace> WebSpaces { get; set; }
public DbSet<SupportChatMessage> SupportChatMessages { get; set; }
public DbSet<IpBan> IpBans { get; set; }
public DbSet<PermissionGroup> PermissionGroups { get; set; }
public DbSet<SecurityLog> SecurityLogs { get; set; }
public DbSet<BlocklistIp> BlocklistIps { get; set; }
public DbSet<WhitelistIp> WhitelistIps { get; set; }
public DbSet<Ticket> Tickets { get; set; }
public DbSet<TicketMessage> TicketMessages { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
var config = ConfigService
.Get()
.Moonlight.Database;
var connectionString = $"host={config.Host};" +
$"port={config.Port};" +
$"database={config.Database};" +
$"uid={config.Username};" +
$"pwd={config.Password}";
optionsBuilder.UseMySql(
connectionString,
ServerVersion.Parse("5.7.37-mysql"),
builder =>
{
builder.EnableRetryOnFailure(5);
}
);
if(ConfigService.SqlDebugMode)
optionsBuilder.AddInterceptors(new SqlLoggingInterceptor());
}
}
}

View file

@ -0,0 +1,10 @@
namespace Moonlight.App.Database.Entities;
public class BlocklistIp
{
public int Id { get; set; }
public string Ip { get; set; } = "";
public DateTime ExpiresAt { get; set; }
public long Packets { get; set; }
public DateTime CreatedAt { get; set; }
}

View file

@ -0,0 +1,10 @@
namespace Moonlight.App.Database.Entities;
public class CloudPanel
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string ApiUrl { get; set; } = "";
public string ApiKey { get; set; } = "";
public string Host { get; set; } = "";
}

View file

@ -0,0 +1,11 @@
namespace Moonlight.App.Database.Entities;
public class DdosAttack
{
public int Id { get; set; }
public bool Ongoing { get; set; }
public long Data { get; set; }
public string Ip { get; set; } = "";
public Node Node { get; set; } = null!;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}

View file

@ -0,0 +1,11 @@
using Newtonsoft.Json;
namespace Moonlight.App.Database.Entities;
public class DockerImage
{
[JsonIgnore]
public int Id { get; set; }
public bool Default { get; set; } = false;
public string Name { get; set; } = "";
}

View file

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.App.Database.Entities;
public class Domain
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public SharedDomain SharedDomain { get; set; }
public User Owner { get; set; }
}

View file

@ -0,0 +1,24 @@
using Newtonsoft.Json;
namespace Moonlight.App.Database.Entities;
public class Image
{
[JsonIgnore]
public int Id { get; set; }
public Guid Uuid { get; set; }
public string Name { get; set; } = "";
public string Description { get; set; } = "";
public string ConfigFiles { get; set; } = "{}";
public string StopCommand { get; set; } = "";
public string StartupDetection { get; set; } = "";
public string InstallScript { get; set; } = "";
public string InstallDockerImage { get; set; } = "";
public string InstallEntrypoint { get; set; } = "";
public string Startup { get; set; } = "";
public int Allocations { get; set; } = 1;
public List<DockerImage> DockerImages { get; set; } = new();
public List<ImageVariable> Variables { get; set; } = new();
public string TagsJson { get; set; } = "";
public string BackgroundImageUrl { get; set; } = "";
}

View file

@ -0,0 +1,11 @@
using Newtonsoft.Json;
namespace Moonlight.App.Database.Entities;
public class ImageVariable
{
[JsonIgnore]
public int Id { get; set; }
public string Key { get; set; } = "";
public string DefaultValue { get; set; } = "";
}

View file

@ -0,0 +1,8 @@
namespace Moonlight.App.Database.Entities;
public class IpBan
{
public int Id { get; set; }
public string Ip { get; set; } = "";
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}

View file

@ -0,0 +1,7 @@
namespace Moonlight.App.Database.Entities;
public class LoadingMessage
{
public int Id { get; set; }
public string Message { get; set; } = "";
}

View file

@ -0,0 +1,9 @@
namespace Moonlight.App.Database.Entities;
public class MySqlDatabase
{
public int Id { get; set; }
public WebSpace WebSpace { get; set; }
public string UserName { get; set; } = "";
public string Password { get; set; } = "";
}

View file

@ -0,0 +1,10 @@
namespace Moonlight.App.Database.Entities;
public class NewsEntry
{
public int Id { get; set; }
public DateTime Date { get; set; }
public string Title { get; set; }
public string Markdown { get; set; }
}

View file

@ -0,0 +1,15 @@
namespace Moonlight.App.Database.Entities;
public class Node
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Fqdn { get; set; } = "";
public string TokenId { get; set; } = "";
public string Token { get; set; } = "";
public int SftpPort { get; set; }
public int HttpPort { get; set; }
public int MoonlightDaemonPort { get; set; }
public List<NodeAllocation> Allocations { get; set; } = new();
public bool Ssl { get; set; } = false;
}

View file

@ -0,0 +1,7 @@
namespace Moonlight.App.Database.Entities;
public class NodeAllocation
{
public int Id { get; set; }
public int Port { get; set; }
}

View file

@ -0,0 +1,8 @@
namespace Moonlight.App.Database.Entities.Notification;
public class NotificationAction
{
public int Id { get; set; }
public NotificationClient NotificationClient { get; set; }
public string Action { get; set; }
}

View file

@ -0,0 +1,7 @@
namespace Moonlight.App.Database.Entities.Notification;
public class NotificationClient
{
public int Id { get; set; }
public User User { get; set; }
}

View file

@ -0,0 +1,8 @@
namespace Moonlight.App.Database.Entities;
public class PermissionGroup
{
public int Id { get; set; }
public string Name { get; set; } = "";
public byte[] Permissions { get; set; } = Array.Empty<byte>();
}

View file

@ -0,0 +1,7 @@
namespace Moonlight.App.Database.Entities;
public class Revoke
{
public int Id { get; set; }
public string Identifier { get; set; } = "";
}

View file

@ -0,0 +1,8 @@
namespace Moonlight.App.Database.Entities;
public class SecurityLog
{
public int Id { get; set; }
public string Text { get; set; } = "";
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}

View file

@ -0,0 +1,26 @@
namespace Moonlight.App.Database.Entities;
public class Server
{
public int Id { get; set; }
public Guid Uuid { get; set; }
public string Name { get; set; } = "";
public int Cpu { get; set; }
public long Memory { get; set; }
public long Disk { get; set; }
public Image Image { get; set; } = null!;
public int DockerImageIndex { get; set; } = 0;
public string OverrideStartup { get; set; } = "";
public bool Installing { get; set; } = false;
public bool Suspended { get; set; } = false;
public bool IsArchived { get; set; } = false;
public ServerBackup? Archive { get; set; } = null;
public List<ServerVariable> Variables { get; set; } = new();
public List<ServerBackup> Backups { get; set; } = new();
public List<NodeAllocation> Allocations { get; set; } = new();
public NodeAllocation? MainAllocation { get; set; } = null;
public Node Node { get; set; } = null!;
public User Owner { get; set; } = null!;
public bool IsCleanupException { get; set; } = false;
}

View file

@ -0,0 +1,11 @@
namespace Moonlight.App.Database.Entities;
public class ServerBackup
{
public int Id { get; set; }
public string Name { get; set; } = "";
public Guid Uuid { get; set; }
public DateTime CreatedAt { get; set; }
public bool Created { get; set; } = false;
public long Bytes { get; set; }
}

View file

@ -0,0 +1,8 @@
namespace Moonlight.App.Database.Entities;
public class ServerVariable
{
public int Id { get; set; }
public string Key { get; set; } = "";
public string Value { get; set; } = "";
}

View file

@ -0,0 +1,8 @@
namespace Moonlight.App.Database.Entities;
public class SharedDomain
{
public int Id { get; set; }
public string Name { get; set; }
public string CloudflareId { get; set; }
}

View file

@ -0,0 +1,12 @@
namespace Moonlight.App.Database.Entities;
public class StatisticsData
{
public int Id { get; set; }
public string Chart { get; set; }
public double Value { get; set; }
public DateTime Date { get; set; }
}

View file

@ -0,0 +1,16 @@
using Moonlight.App.Models.Misc;
namespace Moonlight.App.Database.Entities;
public class Subscription
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Description { get; set; } = "";
public Currency Currency { get; set; } = Currency.USD;
public double Price { get; set; }
public string StripeProductId { get; set; } = "";
public string StripePriceId { get; set; } = "";
public string LimitsJson { get; set; } = "";
public int Duration { get; set; } = 30;
}

View file

@ -0,0 +1,21 @@
using Moonlight.App.Models.Misc;
namespace Moonlight.App.Database.Entities;
public class SupportChatMessage
{
public int Id { get; set; }
public string Content { get; set; } = "";
public string Attachment { get; set; } = "";
public User? Sender { get; set; }
public User Recipient { get; set; }
public bool IsQuestion { get; set; } = false;
public QuestionType QuestionType { get; set; }
public string Answer { get; set; } = "";
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}

View file

@ -0,0 +1,8 @@
namespace Moonlight.App.Database.Entities;
public class SupportChatSnippets
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Description { get; set; } = "";
}

View file

@ -0,0 +1,19 @@
using Moonlight.App.Models.Misc;
namespace Moonlight.App.Database.Entities;
public class Ticket
{
public int Id { get; set; }
public string IssueTopic { get; set; } = "";
public string IssueDescription { get; set; } = "";
public string IssueTries { get; set; } = "";
public User CreatedBy { get; set; }
public User? AssignedTo { get; set; }
public TicketPriority Priority { get; set; }
public TicketStatus Status { get; set; }
public TicketSubject Subject { get; set; }
public int SubjectId { get; set; }
public List<TicketMessage> Messages { get; set; } = new();
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}

View file

@ -0,0 +1,14 @@
namespace Moonlight.App.Database.Entities;
public class TicketMessage
{
public int Id { get; set; }
public string Content { get; set; } = "";
public string? AttachmentUrl { get; set; }
public User? Sender { get; set; }
public bool IsSystemMessage { get; set; }
public bool IsEdited { get; set; }
public bool IsSupportMessage { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
}

View file

@ -0,0 +1,63 @@
using System.ComponentModel.DataAnnotations;
using Moonlight.App.Models.Misc;
namespace Moonlight.App.Database.Entities;
public class User
{
public int Id { get; set; }
// Personal data
public string FirstName { get; set; } = "";
public string LastName { get; set; } = "";
public string Email { get; set; } = "";
public string Password { get; set; } = "";
public string Address { get; set; } = "";
public string City { get; set; } = "";
public string State { get; set; } = "";
public string Country { get; set; } = "";
public string ServerListLayoutJson { get; set; } = "";
// States
public UserStatus Status { get; set; } = UserStatus.Unverified;
public bool Admin { get; set; } = false;
public bool SupportPending { get; set; } = false;
public bool HasRated { get; set; } = false;
public int Rating { get; set; } = 0;
public bool StreamerMode { get; set; } = false;
// Security
public bool TotpEnabled { get; set; } = false;
public string TotpSecret { get; set; } = "";
public DateTime TokenValidTime { get; set; } = DateTime.UtcNow;
public byte[] Permissions { get; set; } = Array.Empty<byte>();
public PermissionGroup? PermissionGroup { get; set; }
// Discord
public ulong DiscordId { get; set; }
// Date stuff
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
public DateTime LastVisitedAt { get; set; } = DateTime.UtcNow;
// Subscriptions
public Subscription? CurrentSubscription { get; set; } = null;
public DateTime SubscriptionSince { get; set; } = DateTime.UtcNow;
public DateTime SubscriptionExpires { get; set; } = DateTime.UtcNow;
// Ip logs
public string RegisterIp { get; set; } = "";
public string LastIp { get; set; } = "";
}

Some files were not shown because too many files have changed in this diff Show more