Compare commits
202 commits
Applicatio
...
v2
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a4080cc1b1 | ||
![]() |
4f5a4913d7 | ||
![]() |
c340e48f02 | ||
![]() |
257af8106d | ||
![]() |
6eedc8aba9 | ||
![]() |
cba98bdf6f | ||
![]() |
d2da868b71 | ||
![]() |
685221b454 | ||
![]() |
f12e5f10d5 | ||
![]() |
cc7b4d7daa | ||
![]() |
769c876dc5 | ||
![]() |
ccec79cca7 | ||
![]() |
e79f2199c3 | ||
![]() |
c53d315bd8 | ||
![]() |
0ae9c27d93 | ||
![]() |
2950034a30 | ||
![]() |
158115bb3b | ||
![]() |
56184a8254 | ||
![]() |
c27b1689f3 | ||
![]() |
3c3dd2af92 | ||
![]() |
125260e7ef | ||
![]() |
b608a0779c | ||
![]() |
7225db0bf1 | ||
![]() |
3f0cdff262 | ||
![]() |
3270039a6a | ||
![]() |
fda972a90e | ||
![]() |
45e81c98bf | ||
![]() |
d9dd9bbf4d | ||
![]() |
160de6443b | ||
![]() |
923a3c18b8 | ||
![]() |
8dc37525ce | ||
![]() |
7bd34842fa | ||
![]() |
da8b01bb98 | ||
![]() |
c9fe469f5b | ||
![]() |
406f7cad65 | ||
![]() |
558e237608 | ||
![]() |
b4251a0f1f | ||
![]() |
0234a8e179 | ||
![]() |
efacaa9b86 | ||
![]() |
7c40d999ff | ||
![]() |
99c14693d5 | ||
![]() |
2cf03d4b68 | ||
![]() |
52bab229ea | ||
![]() |
8b15383b45 | ||
![]() |
eaddefdc8e | ||
![]() |
95cfa815fb | ||
![]() |
870b2516a1 | ||
![]() |
ef982a52ed | ||
![]() |
6ae2390b46 | ||
![]() |
e1fbf601f3 | ||
![]() |
2364a53dd1 | ||
![]() |
be7cecc721 | ||
![]() |
f2aad2ccdf | ||
![]() |
8e76a68b62 | ||
![]() |
6c722a9ac3 | ||
![]() |
52515e7df1 | ||
![]() |
722c56271f | ||
![]() |
9e85c35f59 | ||
![]() |
538a15b609 | ||
![]() |
bb0ab9dc67 | ||
![]() |
87b9b5e1c2 | ||
![]() |
ba0b46db90 | ||
![]() |
ddcbf56abe | ||
![]() |
c553f6f5da | ||
![]() |
5b25774851 | ||
![]() |
01729b982d | ||
![]() |
fd01787dfb | ||
![]() |
90eed5c74c | ||
![]() |
dcfb836b39 | ||
![]() |
610501ef19 | ||
![]() |
48e2e1eb98 | ||
![]() |
f3ad71e33f | ||
![]() |
eaacdb3446 | ||
![]() |
be173e1d48 | ||
![]() |
e3f040c978 | ||
![]() |
e25b005643 | ||
![]() |
4631e66dca | ||
![]() |
73b93f8262 | ||
![]() |
5a1ecebbe9 | ||
![]() |
8dbf458ea3 | ||
![]() |
c5fef04d06 | ||
![]() |
5fb507febc | ||
![]() |
50d6954829 | ||
![]() |
e5f4fd9d62 | ||
![]() |
7da87fb065 | ||
![]() |
b81646c1d4 | ||
![]() |
752f84127c | ||
![]() |
bf1b9533c8 | ||
![]() |
feddea1a69 | ||
![]() |
20fcd5015e | ||
![]() |
9abf32b288 | ||
![]() |
5d9c32a196 | ||
![]() |
cdc2954d0b | ||
![]() |
b2929fe211 | ||
![]() |
3a74f3abcd | ||
![]() |
49077e7023 | ||
![]() |
44b2d07fdb | ||
![]() |
0ee4f3fe04 | ||
![]() |
456d87f262 | ||
![]() |
e47a4c29f7 | ||
![]() |
f172d765e3 | ||
![]() |
9bf129f1ad | ||
![]() |
1cb603a3f3 | ||
![]() |
0a807605ad | ||
![]() |
e20415a5bd | ||
![]() |
15a3789174 | ||
![]() |
823970f617 | ||
![]() |
5a025eb75b | ||
![]() |
bf6641c151 | ||
![]() |
f18877f9b1 | ||
![]() |
c3679afed7 | ||
![]() |
a0ca9af5c9 | ||
![]() |
d1f73e6d78 | ||
![]() |
368886c95c | ||
![]() |
86f3957028 | ||
![]() |
6ec86fdc25 | ||
![]() |
068858f3a1 | ||
![]() |
8d11d2360e | ||
![]() |
970bca7121 | ||
![]() |
07c09e48e3 | ||
![]() |
b2c816cafb | ||
![]() |
960a0bceff | ||
![]() |
aaf4c05630 | ||
![]() |
fada1a11b0 | ||
![]() |
dfa34a6808 | ||
![]() |
1b427607d1 | ||
![]() |
70445069fd | ||
![]() |
423616b9f3 | ||
![]() |
26ed50c94b | ||
![]() |
caa34dd79d | ||
![]() |
0eabe27196 | ||
![]() |
dfc2b5af17 | ||
![]() |
955946d0a6 | ||
![]() |
9e515d9ed7 | ||
![]() |
95507fd41f | ||
![]() |
8d75b30ae4 | ||
![]() |
64bcfe74e7 | ||
![]() |
2729564495 | ||
![]() |
0ec6949095 | ||
![]() |
681403ec6e | ||
![]() |
aaee81e9c4 | ||
![]() |
4e5124cc1b | ||
![]() |
99a7d7bd73 | ||
![]() |
6fd1336f1c | ||
![]() |
33c1ffa0ba | ||
![]() |
19001e5836 | ||
![]() |
12bc66a95b | ||
![]() |
63b2b40227 | ||
![]() |
bb53f1c40a | ||
![]() |
46f08059d7 | ||
![]() |
a9af1ec15e | ||
![]() |
9179d6825c | ||
![]() |
4816befa71 | ||
![]() |
67c846ddc8 | ||
![]() |
79d860351c | ||
![]() |
c1216ea708 | ||
![]() |
a11569a737 | ||
![]() |
cd4feec58f | ||
![]() |
518ec7055a | ||
![]() |
2552b92e5d | ||
![]() |
e9d3ab5307 | ||
![]() |
becc67c46b | ||
![]() |
c3a0833410 | ||
![]() |
da53a0eef7 | ||
![]() |
289f8921ff | ||
![]() |
e1a0cfeebb | ||
![]() |
55a7d71c7f | ||
![]() |
8d1cb47a8a | ||
![]() |
2510d6748c | ||
![]() |
f17ff9246d | ||
![]() |
a2a9a6e21d | ||
![]() |
0e1ddfbccb | ||
![]() |
2edf8b4a9f | ||
![]() |
e47cac71fc | ||
![]() |
0aa28d9764 | ||
![]() |
8b032462c0 | ||
![]() |
3ae694a3da | ||
![]() |
741d13b18a | ||
![]() |
0d8cc5bd5d | ||
![]() |
04ef9dc827 | ||
![]() |
c11ff632d2 | ||
![]() |
c5a3c0550c | ||
![]() |
a67829035e | ||
![]() |
f57aac4f6c | ||
![]() |
3a53fa0a3c | ||
![]() |
7145890801 | ||
![]() |
6d5a5fd16c | ||
![]() |
3092daaad4 | ||
![]() |
0f989a38c3 | ||
![]() |
e8706cad1c | ||
![]() |
d55490dd51 | ||
![]() |
a1cd6b5cd9 | ||
![]() |
0e43278bdd | ||
![]() |
d8bb2b7356 | ||
![]() |
f779e5e920 | ||
![]() |
c57ad9cce7 | ||
![]() |
b492d65efb | ||
![]() |
332937f964 | ||
![]() |
f5501f77fe | ||
![]() |
30bfae96fd | ||
![]() |
d95d613a57 | ||
![]() |
1c96f9d13c |
685 changed files with 22527 additions and 14168 deletions
8
.gitattributes
vendored
8
.gitattributes
vendored
|
@ -1,10 +1,2 @@
|
|||
# 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
|
||||
|
|
2
.github/FUNDING.yml
vendored
Normal file
2
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
# These are supported funding model platforms
|
||||
ko_fi: masuowo
|
87
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
87
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
name: Bug Report
|
||||
description: Something isn't working quite right in the software.
|
||||
labels: [not confirmed]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Bug reports should only be used for reporting issues with how the software works. For assistance installing this software, as well as debugging issues with dependencies, please use our [Discord server](https://discord.gg/TJaspT7A8p).
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Current Behavior
|
||||
description: Please provide a clear & concise description of the issue.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: Please describe what you expected to happen.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: Please be as detailed as possible when providing steps to reproduce, failure to provide steps will result in this issue being closed.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: panel-version
|
||||
attributes:
|
||||
label: Panel Version
|
||||
description: Version number of your Panel (latest is not a version)
|
||||
placeholder: v2 EA
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: daemon-version
|
||||
attributes:
|
||||
label: Daemon Version
|
||||
description: Version number of your Daemon (latest is not a version)
|
||||
placeholder: v2 EA
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: image-details
|
||||
attributes:
|
||||
label: Games and/or Images Affected
|
||||
description: Please include the specific game(s) or Image(s) you are running into this bug with.
|
||||
placeholder: Minecraft (Paper), Minecraft (Forge)
|
||||
|
||||
- type: input
|
||||
id: docker-image
|
||||
attributes:
|
||||
label: Docker Image
|
||||
description: The specific Docker image you are using for the game(s) above.
|
||||
placeholder: ghcr.io/xxx/yolks:java_17
|
||||
|
||||
- type: textarea
|
||||
id: panel-logs
|
||||
attributes:
|
||||
label: Error Logs
|
||||
description: |
|
||||
Run the following command to collect logs on your system.
|
||||
|
||||
Panel: `docker logs moonlight`
|
||||
Wings: `sudo wings diagnostics`
|
||||
placeholder: logs here
|
||||
render: bash
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing issue for this?
|
||||
description: Please [search here](https://github.com/Moonlight-Panel/Moonlight/issues) to see if an issue already exists for your problem.
|
||||
options:
|
||||
- label: I have searched the existing issues before opening this issue.
|
||||
required: true
|
||||
- label: I have provided all relevant details, including the specific game and Docker images I am using if this issue is related to running a server.
|
||||
required: true
|
||||
- label: I have checked in the Discord server and believe this is a bug with the software, and not a configuration issue with my specific system.
|
||||
required: true
|
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Installation Help
|
||||
url: https://discord.gg/TJaspT7A8p
|
||||
about: Please visit our Discord for help with your installation.
|
||||
- name: General Question
|
||||
url: https://discord.gg/TJaspT7A8p
|
||||
about: Please visit our Discord for general questions about Moonlight Panel.
|
32
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
32
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
name: Feature Request
|
||||
description: Suggest a new feature or improvement for the software.
|
||||
labels: [feature request]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Is there an existing feature request for this?
|
||||
description: Please [search here](https://github.com/Moonlight-Panel/Moonlight/issues?q=is%3Aissue) to see if someone else has already suggested this.
|
||||
options:
|
||||
- label: I have searched the existing issues before opening this feature request.
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the feature you would like to see.
|
||||
description: "A clear & concise description of the feature you'd like to have added, and what issues it would solve."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the solution you'd like.
|
||||
description: "You must explain how you'd like to see this feature implemented. Technical implementation details are not necessary, rather an idea of how you'd like to see this feature used."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context to this request.
|
||||
description: "Add any other context or screenshots about the feature request."
|
||||
validations:
|
||||
required: false
|
432
.gitignore
vendored
432
.gitignore
vendored
|
@ -1,44 +1,404 @@
|
|||
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/
|
||||
## 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
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
.vs/
|
||||
*.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/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
_UpgradeReport_Files/
|
||||
[Pp]ackages/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
Thumbs.db
|
||||
Desktop.ini
|
||||
.DS_Store
|
||||
.idea/.idea.Moonlight/.idea/discord.xml
|
||||
# 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
|
||||
|
||||
# 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
|
||||
|
||||
storage/
|
||||
.idea/.idea.Moonlight/.idea/dataSources.xml
|
||||
Moonlight/wwwroot/css/theme.css
|
||||
Moonlight/wwwroot/css/theme.css.map
|
||||
storage/
|
||||
.idea/.idea.Moonlight/.idea/discord.xml
|
||||
|
|
13
.idea/.idea.Moonlight/.idea/.gitignore
generated
vendored
Normal file
13
.idea/.idea.Moonlight/.idea/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Rider ignored files
|
||||
/modules.xml
|
||||
/contentModel.xml
|
||||
/projectSettingsUpdater.xml
|
||||
/.idea.Moonlight.iml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
12
.idea/.idea.Moonlight/.idea/discord.xml
generated
Normal file
12
.idea/.idea.Moonlight/.idea/discord.xml
generated
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?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>
|
21
.idea/.idea.Moonlight/.idea/efCoreCommonOptions.xml
generated
21
.idea/.idea.Moonlight/.idea/efCoreCommonOptions.xml
generated
|
@ -1,21 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EfCoreCommonOptions">
|
||||
<option name="migrationsToStartupProjects">
|
||||
<map>
|
||||
<entry key="691e5ec2-4b4f-4bd1-9cbc-7d3c6efc12da" value="691e5ec2-4b4f-4bd1-9cbc-7d3c6efc12da" />
|
||||
</map>
|
||||
</option>
|
||||
<option name="solutionLevelOptions">
|
||||
<map>
|
||||
<entry key="migrationsProject" value="691e5ec2-4b4f-4bd1-9cbc-7d3c6efc12da" />
|
||||
<entry key="startupProject" value="691e5ec2-4b4f-4bd1-9cbc-7d3c6efc12da" />
|
||||
</map>
|
||||
</option>
|
||||
<option name="startupToMigrationsProjects">
|
||||
<map>
|
||||
<entry key="691e5ec2-4b4f-4bd1-9cbc-7d3c6efc12da" value="691e5ec2-4b4f-4bd1-9cbc-7d3c6efc12da" />
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
14
.idea/.idea.Moonlight/.idea/efCoreDialogsState.xml
generated
14
.idea/.idea.Moonlight/.idea/efCoreDialogsState.xml
generated
|
@ -1,14 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EfCoreDialogsState">
|
||||
<option name="keyValueStorage">
|
||||
<map>
|
||||
<entry key="Common:691e5ec2-4b4f-4bd1-9cbc-7d3c6efc12da: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>
|
13
.idea/.idea.Moonlight/.idea/material_theme_project_new.xml
generated
Normal file
13
.idea/.idea.Moonlight/.idea/material_theme_project_new.xml
generated
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?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>
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RiderProjectSettingsUpdater">
|
||||
<option name="vcsConfiguration" value="2" />
|
||||
</component>
|
||||
</project>
|
2
.idea/.idea.Moonlight/.idea/vcs.xml
generated
2
.idea/.idea.Moonlight/.idea/vcs.xml
generated
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
121
LICENSE
Normal file
121
LICENSE
Normal file
|
@ -0,0 +1,121 @@
|
|||
Creative Commons Legal Code
|
||||
|
||||
CC0 1.0 Universal
|
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||
HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer
|
||||
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||
authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for
|
||||
the purpose of contributing to a commons of creative, cultural and
|
||||
scientific works ("Commons") that the public can reliably and without fear
|
||||
of later claims of infringement build upon, modify, incorporate in other
|
||||
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||
and for any purposes, including without limitation commercial purposes.
|
||||
These owners may contribute to the Commons to promote the ideal of a free
|
||||
culture and the further production of creative, cultural and scientific
|
||||
works, or to gain reputation or greater distribution for their Work in
|
||||
part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any
|
||||
expectation of additional consideration or compensation, the person
|
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||
protected by copyright and related or neighboring rights ("Copyright and
|
||||
Related Rights"). Copyright and Related Rights include, but are not
|
||||
limited to, the following:
|
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display,
|
||||
communicate, and translate a Work;
|
||||
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||
iii. publicity and privacy rights pertaining to a person's image or
|
||||
likeness depicted in a Work;
|
||||
iv. rights protecting against unfair competition in regards to a Work,
|
||||
subject to the limitations in paragraph 4(a), below;
|
||||
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||
in a Work;
|
||||
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||
European Parliament and of the Council of 11 March 1996 on the legal
|
||||
protection of databases, and under any national implementation
|
||||
thereof, including any amended or successor version of such
|
||||
directive); and
|
||||
vii. other similar, equivalent or corresponding rights throughout the
|
||||
world based on applicable law or treaty, and any national
|
||||
implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||
of action, whether now known or unknown (including existing as well as
|
||||
future claims and causes of action), in the Work (i) in all territories
|
||||
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||
treaty (including future time extensions), (iii) in any current or future
|
||||
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||
including without limitation commercial, advertising or promotional
|
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||
member of the public at large and to the detriment of Affirmer's heirs and
|
||||
successors, fully intending that such Waiver shall not be subject to
|
||||
revocation, rescission, cancellation, termination, or any other legal or
|
||||
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||
as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||
be judged legally invalid or ineffective under applicable law, then the
|
||||
Waiver shall be preserved to the maximum extent permitted taking into
|
||||
account Affirmer's express Statement of Purpose. In addition, to the
|
||||
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||
maximum duration provided by applicable law or treaty (including future
|
||||
time extensions), (iii) in any current or future medium and for any number
|
||||
of copies, and (iv) for any purpose whatsoever, including without
|
||||
limitation commercial, advertising or promotional purposes (the
|
||||
"License"). The License shall be deemed effective as of the date CC0 was
|
||||
applied by Affirmer to the Work. Should any part of the License for any
|
||||
reason be judged legally invalid or ineffective under applicable law, such
|
||||
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||
of the License, and in such case Affirmer hereby affirms that he or she
|
||||
will not (i) exercise any of his or her remaining Copyright and Related
|
||||
Rights in the Work or (ii) assert any associated claims and causes of
|
||||
action with respect to the Work, in either case contrary to Affirmer's
|
||||
express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||
surrendered, licensed or otherwise affected by this document.
|
||||
b. Affirmer offers the Work as-is and makes no representations or
|
||||
warranties of any kind concerning the Work, express, implied,
|
||||
statutory or otherwise, including without limitation warranties of
|
||||
title, merchantability, fitness for a particular purpose, non
|
||||
infringement, or the absence of latent or other defects, accuracy, or
|
||||
the present or absence of errors, whether or not discoverable, all to
|
||||
the greatest extent permissible under applicable law.
|
||||
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||
that may apply to the Work or any use thereof, including without
|
||||
limitation any person's Copyright and Related Rights in the Work.
|
||||
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||
consents, permissions or other rights required for any use of the
|
||||
Work.
|
||||
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||
party to this document and has no duty or obligation with respect to
|
||||
this CC0 or use of the Work.
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moonlight", "Moonlight\Moonlight.csproj", "{691E5EC2-4B4F-4BD1-9CBC-7D3C6EFC12DA}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Moonlight", "Moonlight\Moonlight.csproj", "{B9AD26D2-AAA7-4C57-884D-5AACAA54D5B6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -8,9 +8,11 @@ Global
|
|||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{691E5EC2-4B4F-4BD1-9CBC-7D3C6EFC12DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{691E5EC2-4B4F-4BD1-9CBC-7D3C6EFC12DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{691E5EC2-4B4F-4BD1-9CBC-7D3C6EFC12DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{691E5EC2-4B4F-4BD1-9CBC-7D3C6EFC12DA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{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
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
6
Moonlight/.idea/.gitignore
generated
vendored
6
Moonlight/.idea/.gitignore
generated
vendored
|
@ -1,6 +0,0 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
1
Moonlight/.idea/.name
generated
1
Moonlight/.idea/.name
generated
|
@ -1 +0,0 @@
|
|||
data.sqlite
|
6
Moonlight/.idea/vcs.xml
generated
6
Moonlight/.idea/vcs.xml
generated
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
26
Moonlight/App.razor
Normal file
26
Moonlight/App.razor
Normal file
|
@ -0,0 +1,26 @@
|
|||
@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>
|
|
@ -1,22 +0,0 @@
|
|||
using Moonlight.App.Database.Entities.Store;
|
||||
using Moonlight.App.Models.Abstractions;
|
||||
|
||||
namespace Moonlight.App.Actions.Dummy;
|
||||
|
||||
public class DummyActions : ServiceActions
|
||||
{
|
||||
public override Task Create(IServiceProvider provider, Service service)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task Update(IServiceProvider provider, Service service)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public override Task Delete(IServiceProvider provider, Service service)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
namespace Moonlight.App.Api;
|
||||
|
||||
public abstract class AbstractRequest
|
||||
{
|
||||
public IServiceProvider ServiceProvider { get; set; }
|
||||
public ApiUserContext? Context { get; set; }
|
||||
public abstract void ReadData(RequestDataContext dataContext);
|
||||
public abstract Task ProcessRequest();
|
||||
public abstract ResponseDataBuilder CreateResponse(ResponseDataBuilder builder);
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
using System.Net.WebSockets;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Moonlight.App.Api;
|
||||
|
||||
public class ApiManagementService
|
||||
{
|
||||
public Dictionary<int, Type> Requests;
|
||||
public List<ApiUserContext> Contexts;
|
||||
private readonly IServiceProvider ServiceProvider;
|
||||
|
||||
public ApiManagementService(IServiceProvider serviceProvider)
|
||||
{
|
||||
Requests = new Dictionary<int, Type>();
|
||||
Contexts = new List<ApiUserContext>();
|
||||
ServiceProvider = serviceProvider;
|
||||
|
||||
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
|
||||
foreach (var assembly in assemblies)
|
||||
{
|
||||
var types = assembly.ExportedTypes;
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
var attribute = type.GetCustomAttribute<ApiRequestAttribute>();
|
||||
|
||||
if(attribute == null)
|
||||
continue;
|
||||
|
||||
var id = attribute.Id;
|
||||
Requests[id] = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AbstractRequest GetRequest(int id, ApiUserContext context)
|
||||
{
|
||||
var type = Requests[id];
|
||||
var obj = Activator.CreateInstance(type) as AbstractRequest;
|
||||
obj!.Context = context;
|
||||
obj!.ServiceProvider = ServiceProvider.CreateScope().ServiceProvider;
|
||||
|
||||
return obj!;
|
||||
}
|
||||
|
||||
public async Task HandleRequest(ApiUserContext context, byte[] data)
|
||||
{
|
||||
var rqd = new RequestDataContext(data);
|
||||
var id = rqd.ReadInt();
|
||||
var request = GetRequest(id, context);
|
||||
|
||||
request.ReadData(rqd);
|
||||
await request.ProcessRequest();
|
||||
|
||||
var rbd = new ResponseDataBuilder();
|
||||
rbd = request.CreateResponse(rbd);
|
||||
|
||||
CancellationToken t = new CancellationToken();
|
||||
var bytes = rbd.ToBytes();
|
||||
await context.WebSocket.SendAsync(bytes, WebSocketMessageType.Binary, true, t);
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
namespace Moonlight.App.Api;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||
public sealed class ApiRequestAttribute : Attribute
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public ApiRequestAttribute(int id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
using System.Net.WebSockets;
|
||||
using Moonlight.App.Database.Entities;
|
||||
|
||||
namespace Moonlight.App.Api;
|
||||
|
||||
public class ApiUserContext
|
||||
{
|
||||
public ApiUserContext(WebSocket webSocket)
|
||||
{
|
||||
WebSocket = webSocket;
|
||||
}
|
||||
|
||||
public User? User { get; set; }
|
||||
public WebSocket WebSocket { get; }
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
using System.Buffers.Binary;
|
||||
using System.Text;
|
||||
|
||||
namespace Moonlight.App.Api;
|
||||
|
||||
public class RequestDataContext
|
||||
{
|
||||
private List<byte> Data;
|
||||
|
||||
public RequestDataContext(byte[] data)
|
||||
{
|
||||
Data = data.ToList();
|
||||
}
|
||||
|
||||
public int ReadInt()
|
||||
{
|
||||
var bytes = Data.Take(4).ToList();
|
||||
Data.RemoveRange(0, 4);
|
||||
|
||||
if (BitConverter.IsLittleEndian) // because of java (the app needing the api is written in java/kotlin) we need to use big endian
|
||||
{
|
||||
bytes.Reverse();
|
||||
}
|
||||
|
||||
return BitConverter.ToInt32(bytes.ToArray());
|
||||
}
|
||||
|
||||
public byte ReadByte()
|
||||
{
|
||||
var b = Data[0];
|
||||
Data.RemoveAt(0);
|
||||
return b;
|
||||
}
|
||||
|
||||
public bool ReadBoolean()
|
||||
{
|
||||
var b = ReadByte();
|
||||
|
||||
return b == 255;
|
||||
}
|
||||
|
||||
public String ReadString()
|
||||
{
|
||||
var len = ReadInt();
|
||||
|
||||
var bytes = Data.Take(len).ToList();
|
||||
Data.RemoveRange(0, len);
|
||||
|
||||
return Encoding.UTF8.GetString(bytes.ToArray());
|
||||
}
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Exceptions;
|
||||
using Moonlight.App.Helpers;
|
||||
using Moonlight.App.Models.Abstractions;
|
||||
using Moonlight.App.Models.Enums;
|
||||
using Moonlight.App.Repositories;
|
||||
using Moonlight.App.Services.Utils;
|
||||
using OtpNet;
|
||||
|
||||
namespace Moonlight.App.Api.Requests.Auth;
|
||||
|
||||
[ApiRequest(3)]
|
||||
public class CredentialBasedLoginRequest : AbstractRequest
|
||||
{
|
||||
public string Email { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string Code { get; set; }
|
||||
|
||||
public bool Success { get; set; }
|
||||
public bool RequireTotp { get; set; }
|
||||
/// <summary>
|
||||
/// 0: all fine
|
||||
/// 1: wrong credentials
|
||||
/// 2: Totp enabled
|
||||
/// 3: TotpKey missing
|
||||
/// 4: wrong totp code
|
||||
/// </summary>
|
||||
public int ErrorId { get; set; }
|
||||
public string Token { get; set; } = "";
|
||||
public override ResponseDataBuilder CreateResponse(ResponseDataBuilder builder)
|
||||
{
|
||||
builder.WriteBoolean(Success);
|
||||
builder.WriteBoolean(RequireTotp);
|
||||
builder.WriteInt(ErrorId);
|
||||
builder.WriteString(Token);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public override async Task ProcessRequest()
|
||||
{
|
||||
var userRepository = ServiceProvider.GetService<Repository<User>>();
|
||||
|
||||
var user = userRepository
|
||||
.Get()
|
||||
.FirstOrDefault(x => x.Email == Email);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
Success = false;
|
||||
RequireTotp = false;
|
||||
ErrorId = 1;
|
||||
Token = "";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!HashHelper.Verify(Password, user.Password))
|
||||
{
|
||||
Success = false;
|
||||
RequireTotp = false;
|
||||
ErrorId = 1;
|
||||
Token = "";
|
||||
return;
|
||||
}
|
||||
|
||||
var flags = new FlagStorage(user.Flags); // Construct FlagStorage to check for 2fa
|
||||
|
||||
if (!flags[UserFlag.TotpEnabled])
|
||||
{
|
||||
// No 2fa found on this user so were done here
|
||||
Success = true;
|
||||
RequireTotp = false;
|
||||
ErrorId = 0;
|
||||
Token = await GenerateToken(user);
|
||||
Context!.User = user;
|
||||
return;
|
||||
}
|
||||
|
||||
// If we reach this point, 2fa is enabled so we need to continue validating
|
||||
|
||||
if (string.IsNullOrEmpty(Code))
|
||||
{
|
||||
// This will show an additional 2fa login field
|
||||
Success = false;
|
||||
RequireTotp = true;
|
||||
ErrorId = 2;
|
||||
Token = "";
|
||||
return;
|
||||
}
|
||||
|
||||
if (user.TotpKey == null)
|
||||
{
|
||||
// Hopefully we will never fulfill this check ;)
|
||||
Success = false;
|
||||
RequireTotp = false;
|
||||
ErrorId = 3;
|
||||
Token = "";
|
||||
return;
|
||||
throw new DisplayException("2FA key is missing. Please contact the support to fix your account");
|
||||
}
|
||||
|
||||
// Calculate server side code
|
||||
var totp = new Totp(Base32Encoding.ToBytes(user.TotpKey));
|
||||
var codeServerSide = totp.ComputeTotp();
|
||||
|
||||
if (codeServerSide == Code)
|
||||
{
|
||||
Success = true;
|
||||
RequireTotp = false;
|
||||
ErrorId = 0;
|
||||
Token = await GenerateToken(user);
|
||||
Context!.User = user;
|
||||
return;
|
||||
}
|
||||
|
||||
Success = false;
|
||||
RequireTotp = false;
|
||||
ErrorId = 4;
|
||||
Token = "";
|
||||
}
|
||||
|
||||
public async Task<string> GenerateToken(User user)
|
||||
{
|
||||
var jwtService = ServiceProvider.GetService<JwtService>();
|
||||
|
||||
var token = await jwtService.Create(data =>
|
||||
{
|
||||
data.Add("userId", user.Id.ToString());
|
||||
data.Add("issuedAt", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString());
|
||||
}, TimeSpan.FromDays(365));
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
public override void ReadData(RequestDataContext dataContext)
|
||||
{
|
||||
Email = dataContext.ReadString();
|
||||
Password = dataContext.ReadString();
|
||||
Code = dataContext.ReadString();
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Models.Enums;
|
||||
using Moonlight.App.Repositories;
|
||||
using Moonlight.App.Services;
|
||||
using Moonlight.App.Services.Users;
|
||||
|
||||
namespace Moonlight.App.Api.Requests.Auth;
|
||||
|
||||
[ApiRequest(5)]
|
||||
public class IsEmailVerifiedRequest : AbstractRequest
|
||||
{
|
||||
public bool SendMail { get; set; }
|
||||
public bool MailVerified { get; set; }
|
||||
|
||||
public override async Task ProcessRequest()
|
||||
{
|
||||
if(Context.User == null)
|
||||
return;
|
||||
|
||||
var userRepository = ServiceProvider.GetRequiredService<Repository<User>>();
|
||||
Context.User = userRepository.Get().Where(x => x.Id == Context.User.Id).ToArray()[0];
|
||||
|
||||
if (SendMail && Context.User != null)
|
||||
{
|
||||
var userAuthService = ServiceProvider.GetRequiredService<UserAuthService>();
|
||||
await userAuthService.SendVerification(Context!.User);
|
||||
}
|
||||
|
||||
var configService = ServiceProvider.GetRequiredService<ConfigService>();
|
||||
var reqEmailVerify = configService.Get().Security.EnableEmailVerify;
|
||||
if (Context?.User?.Flags!.Contains(UserFlag.MailVerified.ToString()) ?? false)
|
||||
MailVerified = true;
|
||||
else
|
||||
MailVerified = !reqEmailVerify;
|
||||
|
||||
await Task.Delay(200);
|
||||
}
|
||||
|
||||
public override ResponseDataBuilder CreateResponse(ResponseDataBuilder builder)
|
||||
{
|
||||
builder.WriteBoolean(MailVerified);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public override void ReadData(RequestDataContext dataContext)
|
||||
{
|
||||
SendMail = dataContext.ReadBoolean();
|
||||
}
|
||||
}
|
|
@ -1,181 +0,0 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Reflection;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Event;
|
||||
using Moonlight.App.Exceptions;
|
||||
using Moonlight.App.Extensions;
|
||||
using Moonlight.App.Helpers;
|
||||
using Moonlight.App.Repositories;
|
||||
using Moonlight.App.Services;
|
||||
using Moonlight.App.Services.Utils;
|
||||
|
||||
namespace Moonlight.App.Api.Requests.Auth;
|
||||
|
||||
[ApiRequest(4)]
|
||||
public class RegisterRequest: AbstractRequest
|
||||
{
|
||||
[Required(ErrorMessage = "9")]
|
||||
[EmailAddress(ErrorMessage = "10")]
|
||||
public string Email { get; set; } = "";
|
||||
|
||||
[Required(ErrorMessage = "8")]
|
||||
[MinLength(7, ErrorMessage = "7")]
|
||||
[MaxLength(20, ErrorMessage = "7")]
|
||||
[RegularExpression("^[a-z][a-z0-9]*$", ErrorMessage = "6")]
|
||||
public string Username { get; set; } = "";
|
||||
|
||||
[Required(ErrorMessage = "4")]
|
||||
[MinLength(8, ErrorMessage = "5")]
|
||||
[MaxLength(256, ErrorMessage = "5")]
|
||||
public string Password { get; set; } = "";
|
||||
public string PasswordConfirm { get; set; } = "";
|
||||
|
||||
public bool Success { get; set; }
|
||||
public bool RequireEmailVerify { get; set; }
|
||||
/// <summary>
|
||||
/// Error Codes:
|
||||
/// - 0 all successful
|
||||
/// - 1 email exists
|
||||
/// - 2 username exists
|
||||
/// - 3 passwords do not match
|
||||
/// - 4 password needs to be provided
|
||||
/// - 5 password needs to be between 8 and 256 characters
|
||||
/// - 6 Usernames can only contain lowercase characters and numbers
|
||||
/// - 7 username has to be between 7 and 20 chars
|
||||
/// - 8 username required
|
||||
/// - 9 email required
|
||||
/// - 10 email invalid
|
||||
/// </summary>
|
||||
public int ErrorCode { get; set; }
|
||||
public string Token { get; set; } = "";
|
||||
public override ResponseDataBuilder CreateResponse(ResponseDataBuilder builder)
|
||||
{
|
||||
builder.WriteBoolean(Success);
|
||||
builder.WriteBoolean(RequireEmailVerify);
|
||||
builder.WriteInt(ErrorCode);
|
||||
builder.WriteString(Token);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public override void ReadData(RequestDataContext dataContext)
|
||||
{
|
||||
Email = dataContext.ReadString();
|
||||
Username = dataContext.ReadString();
|
||||
Password = dataContext.ReadString();
|
||||
PasswordConfirm = dataContext.ReadString();
|
||||
}
|
||||
|
||||
public override async Task ProcessRequest()
|
||||
{
|
||||
var userRepository = ServiceProvider.GetRequiredService<Repository<User>>();
|
||||
var configService = ServiceProvider.GetRequiredService<ConfigService>();
|
||||
|
||||
var reqEmailVerify = configService.Get().Security.EnableEmailVerify;
|
||||
// Event though we have form validation i want to
|
||||
// ensure that at least these basic formatting things are done
|
||||
Email = Email.ToLower().Trim();
|
||||
Username = Username.ToLower().Trim();
|
||||
|
||||
if (PasswordConfirm != Password)
|
||||
{
|
||||
Token = "";
|
||||
Success = false;
|
||||
RequireEmailVerify = false;
|
||||
ErrorCode = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsPropertyValid(this.GetProperty(x => x.Email)!, out var errorCd))
|
||||
{
|
||||
Token = "";
|
||||
Success = false;
|
||||
RequireEmailVerify = false;
|
||||
ErrorCode = errorCd;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsPropertyValid(this.GetProperty(x => x.Password)!, out var errorCd1))
|
||||
{
|
||||
Token = "";
|
||||
Success = false;
|
||||
RequireEmailVerify = false;
|
||||
ErrorCode = errorCd1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsPropertyValid(this.GetProperty(x => x.Username)!, out var errorCd2))
|
||||
{
|
||||
Token = "";
|
||||
Success = false;
|
||||
RequireEmailVerify = false;
|
||||
ErrorCode = errorCd2;
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent duplication or username and/or email
|
||||
if (userRepository.Get().Any(x => x.Email == Email))
|
||||
{
|
||||
Token = "";
|
||||
Success = false;
|
||||
RequireEmailVerify = false;
|
||||
ErrorCode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (userRepository.Get().Any(x => x.Username == Username))
|
||||
{
|
||||
Token = "";
|
||||
Success = false;
|
||||
RequireEmailVerify = false;
|
||||
ErrorCode = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
var user = new User()
|
||||
{
|
||||
Username = Username,
|
||||
Email = Email,
|
||||
Password = HashHelper.HashToString(Password)
|
||||
};
|
||||
|
||||
var result = userRepository.Add(user);
|
||||
|
||||
await Events.OnUserRegistered.InvokeAsync(result);
|
||||
|
||||
Token = await GenerateToken(user);
|
||||
Success = true;
|
||||
RequireEmailVerify = reqEmailVerify;
|
||||
ErrorCode = 0;
|
||||
}
|
||||
|
||||
public async Task<string> GenerateToken(User user)
|
||||
{
|
||||
var jwtService = ServiceProvider.GetService<JwtService>();
|
||||
|
||||
var token = await jwtService.Create(data =>
|
||||
{
|
||||
data.Add("userId", user.Id.ToString());
|
||||
data.Add("issuedAt", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString());
|
||||
}, TimeSpan.FromDays(365));
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
private bool IsPropertyValid(PropertyInfo property, out int errorCode)
|
||||
{
|
||||
var attribs = property.GetCustomAttributes<ValidationAttribute>();
|
||||
|
||||
foreach (var a in attribs)
|
||||
{
|
||||
if (!a.IsValid(property.GetValue(this)))
|
||||
{
|
||||
errorCode = int.Parse(a.ErrorMessage);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
errorCode = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Repositories;
|
||||
using Moonlight.App.Services.Utils;
|
||||
|
||||
namespace Moonlight.App.Api.Requests.Auth;
|
||||
|
||||
[ApiRequest(2)]
|
||||
public class TokenBasedLoginRequest: AbstractRequest
|
||||
{
|
||||
private String Token { get; set; }
|
||||
private bool Success { get; set; } = false;
|
||||
public override ResponseDataBuilder CreateResponse(ResponseDataBuilder builder)
|
||||
{
|
||||
builder.WriteBoolean(Success);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public override async Task ProcessRequest()
|
||||
{
|
||||
var jwtService = ServiceProvider.GetRequiredService<JwtService>();
|
||||
var userRepository = ServiceProvider.GetRequiredService<Repository<User>>();
|
||||
if (string.IsNullOrEmpty(Token))
|
||||
return;
|
||||
|
||||
if (!await jwtService.Validate(Token))
|
||||
return;
|
||||
|
||||
var data = await jwtService.Decode(Token);
|
||||
|
||||
if (!data.ContainsKey("userId"))
|
||||
return;
|
||||
|
||||
var userId = int.Parse(data["userId"]);
|
||||
|
||||
var user = userRepository
|
||||
.Get()
|
||||
.FirstOrDefault(x => x.Id == userId);
|
||||
|
||||
if (user == null)
|
||||
return;
|
||||
|
||||
if (!data.ContainsKey("issuedAt"))
|
||||
return;
|
||||
|
||||
var issuedAt = long.Parse(data["issuedAt"]);
|
||||
var issuedAtDateTime = DateTimeOffset.FromUnixTimeSeconds(issuedAt).DateTime;
|
||||
|
||||
// If the valid time is newer then when the token was issued, the token is not longer valid
|
||||
if (user.TokenValidTimestamp > issuedAtDateTime)
|
||||
return;
|
||||
|
||||
Context!.User = user;
|
||||
|
||||
if (Context.User == null) // If the current user is null, stop loading additional data
|
||||
return;
|
||||
|
||||
Success = true;
|
||||
}
|
||||
|
||||
public override void ReadData(RequestDataContext dataContext)
|
||||
{
|
||||
Token = dataContext.ReadString();
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
namespace Moonlight.App.Api.Requests;
|
||||
|
||||
[ApiRequest(1)]
|
||||
public class PingRequest : AbstractRequest
|
||||
{
|
||||
public override void ReadData(RequestDataContext dataContext)
|
||||
{
|
||||
var chunk = dataContext.ReadInt();
|
||||
}
|
||||
|
||||
public override ResponseDataBuilder CreateResponse(ResponseDataBuilder builder)
|
||||
{
|
||||
builder.WriteInt(10324);
|
||||
return builder;
|
||||
}
|
||||
|
||||
public override async Task ProcessRequest()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
using System.Text;
|
||||
|
||||
namespace Moonlight.App.Api;
|
||||
|
||||
public class ResponseDataBuilder
|
||||
{
|
||||
private List<byte> Data;
|
||||
|
||||
public ResponseDataBuilder()
|
||||
{
|
||||
Data = new List<byte>();
|
||||
}
|
||||
|
||||
public void WriteInt(int data)
|
||||
{
|
||||
var bytes = BitConverter.GetBytes(data);
|
||||
|
||||
if (BitConverter.IsLittleEndian) // because of java (the app needing th api is written in java/kotlin) we need to use big endian
|
||||
{
|
||||
bytes = bytes.Reverse().ToArray();
|
||||
}
|
||||
|
||||
Data.AddRange(bytes);
|
||||
}
|
||||
|
||||
public void WriteByte(byte data)
|
||||
{
|
||||
Data.Add(data);
|
||||
}
|
||||
|
||||
public void WriteBoolean(bool data)
|
||||
{
|
||||
WriteByte(data ? (byte)255 : (byte)0);
|
||||
}
|
||||
|
||||
public void WriteString(String data)
|
||||
{
|
||||
var bytes = Encoding.UTF8.GetBytes(data);
|
||||
var len = bytes.Length;
|
||||
|
||||
WriteInt(len);
|
||||
Data.AddRange(bytes);
|
||||
}
|
||||
|
||||
public byte[] ToBytes()
|
||||
{
|
||||
return Data.ToArray();
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
using System.ComponentModel;
|
||||
using Moonlight.App.Helpers;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Moonlight.App.Configuration;
|
||||
|
||||
public class ConfigV1
|
||||
{
|
||||
[JsonProperty("AppUrl")]
|
||||
[Description("The url with which moonlight is accessible from the internet. It must not end with a /")]
|
||||
public string AppUrl { get; set; } = "http://your-moonlight-instance-without-slash.owo";
|
||||
|
||||
[JsonProperty("Security")] public SecurityData Security { get; set; } = new();
|
||||
[JsonProperty("Database")] public DatabaseData Database { get; set; } = new();
|
||||
[JsonProperty("MailServer")] public MailServerData MailServer { get; set; } = new();
|
||||
|
||||
[JsonProperty("Store")] public StoreData Store { get; set; } = new();
|
||||
|
||||
public class StoreData
|
||||
{
|
||||
[JsonProperty("Currency")]
|
||||
[Description("A string value representing the currency which will be shown to a user")]
|
||||
public string Currency { get; set; } = "€";
|
||||
}
|
||||
|
||||
public class SecurityData
|
||||
{
|
||||
[JsonProperty("Token")]
|
||||
[Description("The security token helio will use to encrypt various things like tokens")]
|
||||
public string Token { get; set; } = Guid.NewGuid().ToString().Replace("-", "");
|
||||
|
||||
[JsonProperty("EnableEmailVerify")]
|
||||
[Description("This will users force to verify their email address if they havent already")]
|
||||
public bool EnableEmailVerify { get; set; } = false;
|
||||
}
|
||||
|
||||
public class DatabaseData
|
||||
{
|
||||
[JsonProperty("UseSqlite")]
|
||||
public bool UseSqlite { get; set; } = false;
|
||||
|
||||
[JsonProperty("SqlitePath")]
|
||||
public string SqlitePath { get; set; } = PathBuilder.File("storage", "data.sqlite");
|
||||
|
||||
[JsonProperty("Host")]
|
||||
public string Host { get; set; } = "your.db.host";
|
||||
|
||||
[JsonProperty("Port")]
|
||||
public int Port { get; set; } = 3306;
|
||||
|
||||
[JsonProperty("Username")]
|
||||
public string Username { get; set; } = "moonlight_user";
|
||||
|
||||
[JsonProperty("Password")]
|
||||
public string Password { get; set; } = "s3cr3t";
|
||||
|
||||
[JsonProperty("Database")]
|
||||
public string Database { get; set; } = "moonlight_db";
|
||||
}
|
||||
|
||||
public class MailServerData
|
||||
{
|
||||
[JsonProperty("Host")] public string Host { get; set; } = "your.email.host";
|
||||
|
||||
[JsonProperty("Port")] public int Port { get; set; } = 465;
|
||||
|
||||
[JsonProperty("Email")] public string Email { get; set; } = "noreply@your.email.host";
|
||||
|
||||
[JsonProperty("Password")] public string Password { get; set; } = "s3cr3t";
|
||||
|
||||
[JsonProperty("UseSsl")] public bool UseSsl { get; set; } = true;
|
||||
}
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Database.Entities.Community;
|
||||
using Moonlight.App.Database.Entities.Store;
|
||||
using Moonlight.App.Database.Entities.Tickets;
|
||||
using Moonlight.App.Services;
|
||||
|
||||
namespace Moonlight.App.Database;
|
||||
|
||||
public class DataContext : DbContext
|
||||
{
|
||||
private readonly ConfigService ConfigService;
|
||||
|
||||
public DbSet<User> Users { get; set; }
|
||||
//public DbSet<Ticket> Tickets { get; set; }
|
||||
//public DbSet<TicketMessage> TicketMessages { get; set; }
|
||||
|
||||
// Store
|
||||
public DbSet<Category> Categories { get; set; }
|
||||
public DbSet<Product> Products { get; set; }
|
||||
public DbSet<Service> Services { get; set; }
|
||||
public DbSet<ServiceShare> ServiceShares { get; set; }
|
||||
|
||||
public DbSet<GiftCode> GiftCodes { get; set; }
|
||||
public DbSet<GiftCodeUse> GiftCodeUses { get; set; }
|
||||
|
||||
public DbSet<Coupon> Coupons { get; set; }
|
||||
public DbSet<CouponUse> CouponUses { get; set; }
|
||||
|
||||
// Community
|
||||
public DbSet<Post> Posts { get; set; }
|
||||
public DbSet<PostComment> PostComments { get; set; }
|
||||
public DbSet<PostLike> PostLikes { get; set; }
|
||||
public DbSet<WordFilter> WordFilters { get; set; }
|
||||
|
||||
public DataContext(ConfigService configService)
|
||||
{
|
||||
ConfigService = configService;
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
if (!optionsBuilder.IsConfigured)
|
||||
{
|
||||
var config = ConfigService.Get().Database;
|
||||
|
||||
if (config.UseSqlite)
|
||||
optionsBuilder.UseSqlite($"Data Source={config.SqlitePath}");
|
||||
else
|
||||
{
|
||||
var connectionString = $"host={config.Host};" +
|
||||
$"port={config.Port};" +
|
||||
$"database={config.Database};" +
|
||||
$"uid={config.Username};" +
|
||||
$"pwd={config.Password}";
|
||||
|
||||
optionsBuilder.UseMySql(
|
||||
connectionString,
|
||||
ServerVersion.AutoDetect(connectionString),
|
||||
builder => builder.EnableRetryOnFailure(5)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
using Moonlight.App.Database.Enums;
|
||||
|
||||
namespace Moonlight.App.Database.Entities.Community;
|
||||
|
||||
public class Post
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; } = "";
|
||||
public string Content { get; set; } = "";
|
||||
public User Author { get; set; }
|
||||
public PostType Type { get; set; }
|
||||
public List<PostComment> Comments { get; set; } = new();
|
||||
public List<PostLike> Likes { get; set; } = new();
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
namespace Moonlight.App.Database.Entities.Community;
|
||||
|
||||
public class PostComment
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Content { get; set; } = "";
|
||||
public User Author { get; set; }
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
namespace Moonlight.App.Database.Entities.Community;
|
||||
|
||||
public class PostLike
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public User User { get; set; }
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
namespace Moonlight.App.Database.Entities.Community;
|
||||
|
||||
public class WordFilter
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Filter { get; set; } = "";
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
namespace Moonlight.App.Database.Entities.Store;
|
||||
|
||||
public class Category
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; } = "";
|
||||
public string Description { get; set; } = "";
|
||||
public string Slug { get; set; } = "";
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
namespace Moonlight.App.Database.Entities.Store;
|
||||
|
||||
public class Coupon
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Code { get; set; } = "";
|
||||
public int Percent { get; set; }
|
||||
public int Amount { get; set; }
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
namespace Moonlight.App.Database.Entities.Store;
|
||||
|
||||
public class CouponUse
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public Coupon Coupon { get; set; }
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
namespace Moonlight.App.Database.Entities.Store;
|
||||
|
||||
public class GiftCode
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Code { get; set; } = "";
|
||||
public double Value { get; set; }
|
||||
public int Amount { get; set; }
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
namespace Moonlight.App.Database.Entities.Store;
|
||||
|
||||
public class GiftCodeUse
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public GiftCode GiftCode { get; set; }
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
using Moonlight.App.Database.Enums;
|
||||
|
||||
namespace Moonlight.App.Database.Entities.Store;
|
||||
|
||||
public class Product
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public Category Category { get; set; }
|
||||
|
||||
public string Name { get; set; } = "";
|
||||
public string Description { get; set; } = "";
|
||||
public string Slug { get; set; } = "";
|
||||
|
||||
public double Price { get; set; }
|
||||
public int Stock { get; set; }
|
||||
public int MaxPerUser { get; set; }
|
||||
public int Duration { get; set; }
|
||||
|
||||
public ServiceType Type { get; set; }
|
||||
public string ConfigJson { get; set; } = "{}";
|
||||
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
namespace Moonlight.App.Database.Entities.Store;
|
||||
|
||||
public class Service
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string? Nickname { get; set; }
|
||||
|
||||
public bool Suspended { get; set; } = false;
|
||||
|
||||
public Product Product { get; set; }
|
||||
public string? ConfigJsonOverride { get; set; }
|
||||
|
||||
public User Owner { get; set; }
|
||||
public List<ServiceShare> Shares { get; set; } = new();
|
||||
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
public DateTime RenewAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
namespace Moonlight.App.Database.Entities.Store;
|
||||
|
||||
public class ServiceShare
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public User User { get; set; }
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
namespace Moonlight.App.Database.Entities.Store;
|
||||
|
||||
public class Transaction
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public double Price { get; set; }
|
||||
public string Text { get; set; } = "";
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
using Moonlight.App.Database.Enums;
|
||||
|
||||
namespace Moonlight.App.Database.Entities.Tickets;
|
||||
|
||||
public class Ticket
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public User Creator { get; set; }
|
||||
public string Name { get; set; } = "";
|
||||
public string Description { get; set; } = "";
|
||||
public string Tries { get; set; } = "";
|
||||
public TicketPriority Priority { get; set; } = TicketPriority.Low;
|
||||
public bool Open { get; set; } = true;
|
||||
|
||||
public List<TicketMessage> Messages = new();
|
||||
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
namespace Moonlight.App.Database.Entities.Tickets;
|
||||
|
||||
public class TicketMessage
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public User? Sender { get; set; }
|
||||
public bool IsSupport { get; set; }
|
||||
public string Content { get; set; } = "";
|
||||
public string? Attachment { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
using Moonlight.App.Database.Entities.Store;
|
||||
|
||||
namespace Moonlight.App.Database.Entities;
|
||||
|
||||
public class User
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Username { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string? Avatar { get; set; } = null;
|
||||
public string? TotpKey { get; set; } = null;
|
||||
|
||||
// Store
|
||||
public double Balance { get; set; }
|
||||
public List<Transaction> Transactions { get; set; } = new();
|
||||
|
||||
public List<CouponUse> CouponUses { get; set; } = new();
|
||||
public List<GiftCodeUse> GiftCodeUses { get; set; } = new();
|
||||
|
||||
// Meta data
|
||||
public string Flags { get; set; } = "";
|
||||
public int Permissions { get; set; } = 0;
|
||||
|
||||
// Timestamps
|
||||
public DateTime TokenValidTimestamp { get; set; } = DateTime.UtcNow.AddMinutes(-10);
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
namespace Moonlight.App.Database.Enums;
|
||||
|
||||
public enum PostType
|
||||
{
|
||||
Project = 0,
|
||||
Announcement = 1,
|
||||
Event = 2
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
namespace Moonlight.App.Database.Enums;
|
||||
|
||||
public enum ServiceType
|
||||
{
|
||||
Server,
|
||||
Webspace,
|
||||
Database,
|
||||
Domain
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
namespace Moonlight.App.Database.Enums;
|
||||
|
||||
public enum TicketPriority
|
||||
{
|
||||
Low,
|
||||
Medium,
|
||||
High,
|
||||
Critical
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.App.Database;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
[DbContext(typeof(DataContext))]
|
||||
[Migration("20231013200303_AddedUser")]
|
||||
partial class AddedUser
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Avatar")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Flags")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Permissions")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("TokenValidTimestamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TotpKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedUser : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Users",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Username = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Email = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Password = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Avatar = table.Column<string>(type: "TEXT", nullable: true),
|
||||
TotpKey = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Flags = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Permissions = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
TokenValidTimestamp = table.Column<DateTime>(type: "TEXT", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Users", x => x.Id);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Users");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,341 +0,0 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.App.Database;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
[DbContext(typeof(DataContext))]
|
||||
[Migration("20231017075519_AddStoreModels")]
|
||||
partial class AddStoreModels
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Category", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Coupon", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Amount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Percent")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Coupons");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.CouponUse", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("CouponId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CouponId");
|
||||
|
||||
b.ToTable("CouponUses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Amount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Value")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("GiftCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCodeUse", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("GiftCodeId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GiftCodeId");
|
||||
|
||||
b.ToTable("GiftCodeUses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Product", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("CategoryId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConfigJson")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Duration")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("MaxPerUser")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Price")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Stock")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.ToTable("Products");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConfigJsonOverride")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Nickname")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("OwnerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ProductId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("RenewAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Suspended")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.HasIndex("ProductId");
|
||||
|
||||
b.ToTable("Services");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.ServiceShare", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("ServiceId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ServiceId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("ServiceShares");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Avatar")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Flags")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Permissions")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("TokenValidTimestamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TotpKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.CouponUse", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Coupon", "Coupon")
|
||||
.WithMany()
|
||||
.HasForeignKey("CouponId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Coupon");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCodeUse", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.GiftCode", "GiftCode")
|
||||
.WithMany()
|
||||
.HasForeignKey("GiftCodeId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("GiftCode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Product", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Category", "Category")
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoryId");
|
||||
|
||||
b.Navigation("Category");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||
.WithMany()
|
||||
.HasForeignKey("OwnerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Product", "Product")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProductId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Owner");
|
||||
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.ServiceShare", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Service", null)
|
||||
.WithMany("Shares")
|
||||
.HasForeignKey("ServiceId");
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.Navigation("Shares");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,245 +0,0 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddStoreModels : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Categories",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Description = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Slug = table.Column<string>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Categories", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Coupons",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Code = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Percent = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
Amount = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Coupons", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "GiftCodes",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Code = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Value = table.Column<double>(type: "REAL", nullable: false),
|
||||
Amount = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_GiftCodes", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Products",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
CategoryId = table.Column<int>(type: "INTEGER", nullable: true),
|
||||
Name = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Description = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Slug = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Price = table.Column<double>(type: "REAL", nullable: false),
|
||||
Stock = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
MaxPerUser = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
Duration = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
Type = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ConfigJson = table.Column<string>(type: "TEXT", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Products", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Products_Categories_CategoryId",
|
||||
column: x => x.CategoryId,
|
||||
principalTable: "Categories",
|
||||
principalColumn: "Id");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "CouponUses",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
CouponId = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_CouponUses", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_CouponUses_Coupons_CouponId",
|
||||
column: x => x.CouponId,
|
||||
principalTable: "Coupons",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "GiftCodeUses",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
GiftCodeId = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_GiftCodeUses", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_GiftCodeUses_GiftCodes_GiftCodeId",
|
||||
column: x => x.GiftCodeId,
|
||||
principalTable: "GiftCodes",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Services",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Nickname = table.Column<string>(type: "TEXT", nullable: true),
|
||||
Suspended = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
ProductId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ConfigJsonOverride = table.Column<string>(type: "TEXT", nullable: true),
|
||||
OwnerId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
|
||||
RenewAt = table.Column<DateTime>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Services", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Services_Products_ProductId",
|
||||
column: x => x.ProductId,
|
||||
principalTable: "Products",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_Services_Users_OwnerId",
|
||||
column: x => x.OwnerId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ServiceShares",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
UserId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ServiceId = table.Column<int>(type: "INTEGER", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ServiceShares", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_ServiceShares_Services_ServiceId",
|
||||
column: x => x.ServiceId,
|
||||
principalTable: "Services",
|
||||
principalColumn: "Id");
|
||||
table.ForeignKey(
|
||||
name: "FK_ServiceShares_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_CouponUses_CouponId",
|
||||
table: "CouponUses",
|
||||
column: "CouponId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GiftCodeUses_GiftCodeId",
|
||||
table: "GiftCodeUses",
|
||||
column: "GiftCodeId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Products_CategoryId",
|
||||
table: "Products",
|
||||
column: "CategoryId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Services_OwnerId",
|
||||
table: "Services",
|
||||
column: "OwnerId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Services_ProductId",
|
||||
table: "Services",
|
||||
column: "ProductId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ServiceShares_ServiceId",
|
||||
table: "ServiceShares",
|
||||
column: "ServiceId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ServiceShares_UserId",
|
||||
table: "ServiceShares",
|
||||
column: "UserId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "CouponUses");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "GiftCodeUses");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ServiceShares");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Coupons");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "GiftCodes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Services");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Products");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Categories");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,371 +0,0 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.App.Database;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
[DbContext(typeof(DataContext))]
|
||||
[Migration("20231018203522_AddedUserStoreData")]
|
||||
partial class AddedUserStoreData
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Category", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Coupon", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Amount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Percent")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Coupons");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.CouponUse", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("CouponId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CouponId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("CouponUses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Amount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Value")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("GiftCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCodeUse", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("GiftCodeId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GiftCodeId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("GiftCodeUses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Product", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConfigJson")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Duration")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("MaxPerUser")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Price")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Stock")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.ToTable("Products");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConfigJsonOverride")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Nickname")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("OwnerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ProductId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("RenewAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Suspended")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.HasIndex("ProductId");
|
||||
|
||||
b.ToTable("Services");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.ServiceShare", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("ServiceId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ServiceId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("ServiceShares");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Avatar")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Balance")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Flags")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Permissions")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("TokenValidTimestamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TotpKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.CouponUse", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Coupon", "Coupon")
|
||||
.WithMany()
|
||||
.HasForeignKey("CouponId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("CouponUses")
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("Coupon");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCodeUse", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.GiftCode", "GiftCode")
|
||||
.WithMany()
|
||||
.HasForeignKey("GiftCodeId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("GiftCodeUses")
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("GiftCode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Product", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Category", "Category")
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Category");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||
.WithMany()
|
||||
.HasForeignKey("OwnerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Product", "Product")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProductId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Owner");
|
||||
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.ServiceShare", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Service", null)
|
||||
.WithMany("Shares")
|
||||
.HasForeignKey("ServiceId");
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.Navigation("Shares");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||
{
|
||||
b.Navigation("CouponUses");
|
||||
|
||||
b.Navigation("GiftCodeUses");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedUserStoreData : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Products_Categories_CategoryId",
|
||||
table: "Products");
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "Balance",
|
||||
table: "Users",
|
||||
type: "REAL",
|
||||
nullable: false,
|
||||
defaultValue: 0.0);
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "CategoryId",
|
||||
table: "Products",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "INTEGER",
|
||||
oldNullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "UserId",
|
||||
table: "GiftCodeUses",
|
||||
type: "INTEGER",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "UserId",
|
||||
table: "CouponUses",
|
||||
type: "INTEGER",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_GiftCodeUses_UserId",
|
||||
table: "GiftCodeUses",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_CouponUses_UserId",
|
||||
table: "CouponUses",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_CouponUses_Users_UserId",
|
||||
table: "CouponUses",
|
||||
column: "UserId",
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_GiftCodeUses_Users_UserId",
|
||||
table: "GiftCodeUses",
|
||||
column: "UserId",
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Products_Categories_CategoryId",
|
||||
table: "Products",
|
||||
column: "CategoryId",
|
||||
principalTable: "Categories",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_CouponUses_Users_UserId",
|
||||
table: "CouponUses");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_GiftCodeUses_Users_UserId",
|
||||
table: "GiftCodeUses");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Products_Categories_CategoryId",
|
||||
table: "Products");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_GiftCodeUses_UserId",
|
||||
table: "GiftCodeUses");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_CouponUses_UserId",
|
||||
table: "CouponUses");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Balance",
|
||||
table: "Users");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UserId",
|
||||
table: "GiftCodeUses");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UserId",
|
||||
table: "CouponUses");
|
||||
|
||||
migrationBuilder.AlterColumn<int>(
|
||||
name: "CategoryId",
|
||||
table: "Products",
|
||||
type: "INTEGER",
|
||||
nullable: true,
|
||||
oldClrType: typeof(int),
|
||||
oldType: "INTEGER");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Products_Categories_CategoryId",
|
||||
table: "Products",
|
||||
column: "CategoryId",
|
||||
principalTable: "Categories",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,403 +0,0 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.App.Database;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
[DbContext(typeof(DataContext))]
|
||||
[Migration("20231018204737_AddedTransactions")]
|
||||
partial class AddedTransactions
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Category", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Coupon", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Amount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Percent")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Coupons");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.CouponUse", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("CouponId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CouponId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("CouponUses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Amount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Value")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("GiftCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCodeUse", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("GiftCodeId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GiftCodeId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("GiftCodeUses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Product", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConfigJson")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Duration")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("MaxPerUser")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Price")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Stock")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.ToTable("Products");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConfigJsonOverride")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Nickname")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("OwnerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ProductId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("RenewAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Suspended")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.HasIndex("ProductId");
|
||||
|
||||
b.ToTable("Services");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.ServiceShare", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("ServiceId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ServiceId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("ServiceShares");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Transaction", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("Price")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("Text")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Transaction");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Avatar")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Balance")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Flags")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Permissions")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("TokenValidTimestamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TotpKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.CouponUse", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Coupon", "Coupon")
|
||||
.WithMany()
|
||||
.HasForeignKey("CouponId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("CouponUses")
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("Coupon");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCodeUse", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.GiftCode", "GiftCode")
|
||||
.WithMany()
|
||||
.HasForeignKey("GiftCodeId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("GiftCodeUses")
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("GiftCode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Product", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Category", "Category")
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Category");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||
.WithMany()
|
||||
.HasForeignKey("OwnerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Product", "Product")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProductId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Owner");
|
||||
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.ServiceShare", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Service", null)
|
||||
.WithMany("Shares")
|
||||
.HasForeignKey("ServiceId");
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Transaction", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("Transactions")
|
||||
.HasForeignKey("UserId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.Navigation("Shares");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||
{
|
||||
b.Navigation("CouponUses");
|
||||
|
||||
b.Navigation("GiftCodeUses");
|
||||
|
||||
b.Navigation("Transactions");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedTransactions : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Transaction",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Price = table.Column<double>(type: "REAL", nullable: false),
|
||||
Text = table.Column<string>(type: "TEXT", nullable: false),
|
||||
UserId = table.Column<int>(type: "INTEGER", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Transaction", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Transaction_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id");
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Transaction_UserId",
|
||||
table: "Transaction",
|
||||
column: "UserId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Transaction");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,539 +0,0 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.App.Database;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
[DbContext(typeof(DataContext))]
|
||||
[Migration("20231027105412_AddPostsModels")]
|
||||
partial class AddPostsModels
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.Post", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AuthorId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Content")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AuthorId");
|
||||
|
||||
b.ToTable("Posts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.PostComment", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AuthorId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Content")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("PostId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AuthorId");
|
||||
|
||||
b.HasIndex("PostId");
|
||||
|
||||
b.ToTable("PostComments");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.PostLike", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("PostId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PostId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("PostLikes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Category", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Coupon", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Amount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Percent")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Coupons");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.CouponUse", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("CouponId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CouponId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("CouponUses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Amount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Value")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("GiftCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCodeUse", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("GiftCodeId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GiftCodeId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("GiftCodeUses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Product", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConfigJson")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Duration")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("MaxPerUser")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Price")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Stock")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.ToTable("Products");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConfigJsonOverride")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Nickname")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("OwnerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ProductId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("RenewAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Suspended")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.HasIndex("ProductId");
|
||||
|
||||
b.ToTable("Services");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.ServiceShare", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("ServiceId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ServiceId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("ServiceShares");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Transaction", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("Price")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("Text")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Transaction");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Avatar")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Balance")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Flags")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Permissions")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("TokenValidTimestamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TotpKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.Post", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Author")
|
||||
.WithMany()
|
||||
.HasForeignKey("AuthorId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Author");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.PostComment", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Author")
|
||||
.WithMany()
|
||||
.HasForeignKey("AuthorId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.Community.Post", null)
|
||||
.WithMany("Comments")
|
||||
.HasForeignKey("PostId");
|
||||
|
||||
b.Navigation("Author");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.PostLike", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Community.Post", null)
|
||||
.WithMany("Likes")
|
||||
.HasForeignKey("PostId");
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.CouponUse", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Coupon", "Coupon")
|
||||
.WithMany()
|
||||
.HasForeignKey("CouponId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("CouponUses")
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("Coupon");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCodeUse", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.GiftCode", "GiftCode")
|
||||
.WithMany()
|
||||
.HasForeignKey("GiftCodeId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("GiftCodeUses")
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("GiftCode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Product", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Category", "Category")
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Category");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||
.WithMany()
|
||||
.HasForeignKey("OwnerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Product", "Product")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProductId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Owner");
|
||||
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.ServiceShare", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Service", null)
|
||||
.WithMany("Shares")
|
||||
.HasForeignKey("ServiceId");
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Transaction", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("Transactions")
|
||||
.HasForeignKey("UserId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.Post", b =>
|
||||
{
|
||||
b.Navigation("Comments");
|
||||
|
||||
b.Navigation("Likes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.Navigation("Shares");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||
{
|
||||
b.Navigation("CouponUses");
|
||||
|
||||
b.Navigation("GiftCodeUses");
|
||||
|
||||
b.Navigation("Transactions");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddPostsModels : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Posts",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Title = table.Column<string>(type: "TEXT", nullable: false),
|
||||
Content = table.Column<string>(type: "TEXT", nullable: false),
|
||||
AuthorId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
Type = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Posts", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Posts_Users_AuthorId",
|
||||
column: x => x.AuthorId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PostComments",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Content = table.Column<string>(type: "TEXT", nullable: false),
|
||||
AuthorId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
|
||||
UpdatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
|
||||
PostId = table.Column<int>(type: "INTEGER", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PostComments", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_PostComments_Posts_PostId",
|
||||
column: x => x.PostId,
|
||||
principalTable: "Posts",
|
||||
principalColumn: "Id");
|
||||
table.ForeignKey(
|
||||
name: "FK_PostComments_Users_AuthorId",
|
||||
column: x => x.AuthorId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PostLikes",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
UserId = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "TEXT", nullable: false),
|
||||
PostId = table.Column<int>(type: "INTEGER", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PostLikes", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_PostLikes_Posts_PostId",
|
||||
column: x => x.PostId,
|
||||
principalTable: "Posts",
|
||||
principalColumn: "Id");
|
||||
table.ForeignKey(
|
||||
name: "FK_PostLikes_Users_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PostComments_AuthorId",
|
||||
table: "PostComments",
|
||||
column: "AuthorId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PostComments_PostId",
|
||||
table: "PostComments",
|
||||
column: "PostId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PostLikes_PostId",
|
||||
table: "PostLikes",
|
||||
column: "PostId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PostLikes_UserId",
|
||||
table: "PostLikes",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Posts_AuthorId",
|
||||
table: "Posts",
|
||||
column: "AuthorId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "PostComments");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "PostLikes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Posts");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,554 +0,0 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.App.Database;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
[DbContext(typeof(DataContext))]
|
||||
[Migration("20231028214520_AddedWordFilter")]
|
||||
partial class AddedWordFilter
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.Post", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AuthorId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Content")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AuthorId");
|
||||
|
||||
b.ToTable("Posts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.PostComment", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AuthorId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Content")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("PostId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AuthorId");
|
||||
|
||||
b.HasIndex("PostId");
|
||||
|
||||
b.ToTable("PostComments");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.PostLike", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("PostId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PostId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("PostLikes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.WordFilter", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Filter")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("WordFilters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Category", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Coupon", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Amount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Percent")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Coupons");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.CouponUse", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("CouponId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CouponId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("CouponUses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Amount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Value")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("GiftCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCodeUse", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("GiftCodeId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GiftCodeId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("GiftCodeUses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Product", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConfigJson")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Duration")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("MaxPerUser")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Price")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Stock")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.ToTable("Products");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConfigJsonOverride")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Nickname")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("OwnerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ProductId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("RenewAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Suspended")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.HasIndex("ProductId");
|
||||
|
||||
b.ToTable("Services");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.ServiceShare", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("ServiceId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ServiceId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("ServiceShares");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Transaction", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("Price")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("Text")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Transaction");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Avatar")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Balance")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Flags")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Permissions")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("TokenValidTimestamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TotpKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.Post", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Author")
|
||||
.WithMany()
|
||||
.HasForeignKey("AuthorId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Author");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.PostComment", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Author")
|
||||
.WithMany()
|
||||
.HasForeignKey("AuthorId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.Community.Post", null)
|
||||
.WithMany("Comments")
|
||||
.HasForeignKey("PostId");
|
||||
|
||||
b.Navigation("Author");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.PostLike", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Community.Post", null)
|
||||
.WithMany("Likes")
|
||||
.HasForeignKey("PostId");
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.CouponUse", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Coupon", "Coupon")
|
||||
.WithMany()
|
||||
.HasForeignKey("CouponId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("CouponUses")
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("Coupon");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCodeUse", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.GiftCode", "GiftCode")
|
||||
.WithMany()
|
||||
.HasForeignKey("GiftCodeId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("GiftCodeUses")
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("GiftCode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Product", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Category", "Category")
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Category");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||
.WithMany()
|
||||
.HasForeignKey("OwnerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Product", "Product")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProductId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Owner");
|
||||
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.ServiceShare", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Service", null)
|
||||
.WithMany("Shares")
|
||||
.HasForeignKey("ServiceId");
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Transaction", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("Transactions")
|
||||
.HasForeignKey("UserId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.Post", b =>
|
||||
{
|
||||
b.Navigation("Comments");
|
||||
|
||||
b.Navigation("Likes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.Navigation("Shares");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||
{
|
||||
b.Navigation("CouponUses");
|
||||
|
||||
b.Navigation("GiftCodeUses");
|
||||
|
||||
b.Navigation("Transactions");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedWordFilter : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "WordFilters",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
Filter = table.Column<string>(type: "TEXT", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_WordFilters", x => x.Id);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "WordFilters");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,551 +0,0 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Moonlight.App.Database;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
[DbContext(typeof(DataContext))]
|
||||
partial class DataContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder.HasAnnotation("ProductVersion", "7.0.2");
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.Post", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AuthorId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Content")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AuthorId");
|
||||
|
||||
b.ToTable("Posts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.PostComment", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AuthorId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Content")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("PostId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AuthorId");
|
||||
|
||||
b.HasIndex("PostId");
|
||||
|
||||
b.ToTable("PostComments");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.PostLike", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("PostId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PostId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("PostLikes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.WordFilter", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Filter")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("WordFilters");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Category", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Categories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Coupon", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Amount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Percent")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Coupons");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.CouponUse", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("CouponId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CouponId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("CouponUses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Amount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Code")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Value")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("GiftCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCodeUse", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("GiftCodeId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("GiftCodeId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("GiftCodeUses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Product", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConfigJson")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Duration")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("MaxPerUser")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Price")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Stock")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.ToTable("Products");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConfigJsonOverride")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Nickname")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("OwnerId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ProductId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("RenewAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Suspended")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.HasIndex("ProductId");
|
||||
|
||||
b.ToTable("Services");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.ServiceShare", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int?>("ServiceId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ServiceId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("ServiceShares");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Transaction", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<double>("Price")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("Text")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int?>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Transaction");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Avatar")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<double>("Balance")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Flags")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Permissions")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("TokenValidTimestamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TotpKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.Post", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Author")
|
||||
.WithMany()
|
||||
.HasForeignKey("AuthorId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Author");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.PostComment", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Author")
|
||||
.WithMany()
|
||||
.HasForeignKey("AuthorId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.Community.Post", null)
|
||||
.WithMany("Comments")
|
||||
.HasForeignKey("PostId");
|
||||
|
||||
b.Navigation("Author");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.PostLike", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Community.Post", null)
|
||||
.WithMany("Likes")
|
||||
.HasForeignKey("PostId");
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.CouponUse", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Coupon", "Coupon")
|
||||
.WithMany()
|
||||
.HasForeignKey("CouponId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("CouponUses")
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("Coupon");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.GiftCodeUse", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.GiftCode", "GiftCode")
|
||||
.WithMany()
|
||||
.HasForeignKey("GiftCodeId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("GiftCodeUses")
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("GiftCode");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Product", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Category", "Category")
|
||||
.WithMany()
|
||||
.HasForeignKey("CategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Category");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||
.WithMany()
|
||||
.HasForeignKey("OwnerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Product", "Product")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProductId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Owner");
|
||||
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.ServiceShare", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.Store.Service", null)
|
||||
.WithMany("Shares")
|
||||
.HasForeignKey("ServiceId");
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Transaction", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", null)
|
||||
.WithMany("Transactions")
|
||||
.HasForeignKey("UserId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Community.Post", b =>
|
||||
{
|
||||
b.Navigation("Comments");
|
||||
|
||||
b.Navigation("Likes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Store.Service", b =>
|
||||
{
|
||||
b.Navigation("Shares");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||
{
|
||||
b.Navigation("CouponUses");
|
||||
|
||||
b.Navigation("GiftCodeUses");
|
||||
|
||||
b.Navigation("Transactions");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
using Moonlight.App.Database.Entities;
|
||||
|
||||
namespace Moonlight.App.Event.Args;
|
||||
|
||||
public class MailVerificationEventArgs
|
||||
{
|
||||
public User User { get; set; }
|
||||
public string Jwt { get; set; }
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Database.Entities.Store;
|
||||
|
||||
namespace Moonlight.App.Event.Args;
|
||||
|
||||
public class TransactionCreatedEventArgs
|
||||
{
|
||||
public Transaction Transaction { get; set; }
|
||||
public User User { get; set; }
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Database.Entities.Community;
|
||||
using Moonlight.App.Database.Entities.Store;
|
||||
using Moonlight.App.Event.Args;
|
||||
|
||||
namespace Moonlight.App.Event;
|
||||
|
||||
public class Events
|
||||
{
|
||||
public static EventHandler<User> OnUserRegistered;
|
||||
public static EventHandler<User> OnUserPasswordChanged;
|
||||
public static EventHandler<User> OnUserTotpSet;
|
||||
public static EventHandler<MailVerificationEventArgs> OnUserMailVerify;
|
||||
public static EventHandler<Service> OnServiceOrdered;
|
||||
public static EventHandler<TransactionCreatedEventArgs> OnTransactionCreated;
|
||||
public static EventHandler<Post> OnPostCreated;
|
||||
public static EventHandler<Post> OnPostUpdated;
|
||||
public static EventHandler<Post> OnPostDeleted;
|
||||
public static EventHandler<Post> OnPostLiked;
|
||||
public static EventHandler<PostComment> OnPostCommentCreated;
|
||||
public static EventHandler<PostComment> OnPostCommentDeleted;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
namespace Moonlight.App.Exceptions;
|
||||
|
||||
public class DisplayException : Exception
|
||||
{
|
||||
public DisplayException()
|
||||
{
|
||||
}
|
||||
|
||||
public DisplayException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public DisplayException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
using Moonlight.App.Models.Enums;
|
||||
|
||||
namespace Moonlight.App.Extensions.Attributes;
|
||||
|
||||
public class RequirePermissionAttribute : Attribute
|
||||
{
|
||||
public int PermissionInteger = 0;
|
||||
|
||||
public RequirePermissionAttribute(){}
|
||||
|
||||
public RequirePermissionAttribute(int perms)
|
||||
{
|
||||
PermissionInteger = perms;
|
||||
}
|
||||
|
||||
public RequirePermissionAttribute(Permission permission)
|
||||
{
|
||||
PermissionInteger = (int)permission;
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
namespace Moonlight.App.Extensions.Attributes;
|
||||
|
||||
public class SelectorAttribute : Attribute
|
||||
{
|
||||
public string SelectorProp { get; set; } = "";
|
||||
public string DisplayProp { get; set; } = "";
|
||||
public bool UseDropdown { get; set; } = false;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
using System.Text;
|
||||
|
||||
namespace Moonlight.App.Extensions;
|
||||
|
||||
public static class ConfigurationBuilderExtensions
|
||||
{
|
||||
public static IConfigurationBuilder AddJsonString(this IConfigurationBuilder configurationBuilder, string json)
|
||||
{
|
||||
var bytes = Encoding.UTF8.GetBytes(json);
|
||||
var stream = new MemoryStream(bytes);
|
||||
return configurationBuilder.AddJsonStream(stream);
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
namespace Moonlight.App.Extensions;
|
||||
|
||||
public static class EventHandlerExtensions
|
||||
{
|
||||
public static async Task InvokeAsync(this EventHandler handler)
|
||||
{
|
||||
var tasks = handler
|
||||
.GetInvocationList()
|
||||
.Select(x => new Task(() => x.DynamicInvoke(null, null)))
|
||||
.ToArray();
|
||||
|
||||
foreach (var task in tasks)
|
||||
{
|
||||
task.Start();
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
public static async Task InvokeAsync<T>(this EventHandler<T>? handler, T? data = default(T))
|
||||
{
|
||||
if(handler == null)
|
||||
return;
|
||||
|
||||
var tasks = handler
|
||||
.GetInvocationList()
|
||||
.Select(x => new Task(() => x.DynamicInvoke(null, data)))
|
||||
.ToArray();
|
||||
|
||||
foreach (var task in tasks)
|
||||
{
|
||||
task.Start();
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Moonlight.App.Extensions;
|
||||
|
||||
public static class TypeExtensions
|
||||
{
|
||||
public static PropertyInfo? GetProperty<T, TValue>(this T type, Expression<Func<T, TValue>> selector)
|
||||
where T : class
|
||||
{
|
||||
Expression expression = selector.Body;
|
||||
|
||||
return expression.NodeType == ExpressionType.MemberAccess
|
||||
? (PropertyInfo) ((MemberExpression) expression).Member
|
||||
: null;
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public static class ComponentHelper
|
||||
{
|
||||
public static RenderFragment FromType(Type type) => builder =>
|
||||
{
|
||||
builder.OpenComponent(0, type);
|
||||
builder.CloseComponent();
|
||||
};
|
||||
}
|
|
@ -1,280 +0,0 @@
|
|||
using System.Text;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public static class Formatter
|
||||
{
|
||||
public static string GenerateString(int length)
|
||||
{
|
||||
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
var stringBuilder = new StringBuilder();
|
||||
var random = new Random();
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
stringBuilder.Append(chars[random.Next(chars.Length)]);
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
public static string IntToStringWithLeadingZeros(int number, int n)
|
||||
{
|
||||
string result = number.ToString();
|
||||
int length = result.Length;
|
||||
|
||||
for (int i = length; i < n; i++)
|
||||
{
|
||||
result = "0" + result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string CapitalizeFirstCharacter(string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input))
|
||||
{
|
||||
return input;
|
||||
}
|
||||
|
||||
char firstChar = char.ToUpper(input[0]);
|
||||
string restOfString = input.Substring(1);
|
||||
|
||||
return firstChar + restOfString;
|
||||
}
|
||||
|
||||
public static string CutInHalf(string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input))
|
||||
return input;
|
||||
|
||||
int length = input.Length;
|
||||
int halfLength = length / 2;
|
||||
|
||||
return input.Substring(0, halfLength);
|
||||
}
|
||||
|
||||
public static bool EndsInOneOf(string suffix, IEnumerable<string> strings)
|
||||
{
|
||||
foreach (string str in strings)
|
||||
{
|
||||
if (suffix.EndsWith(str))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ContainsOneOf(string textToSearch, IEnumerable<string> strings, out string foundText)
|
||||
{
|
||||
foreach (string str in strings)
|
||||
{
|
||||
if (textToSearch.Contains(str))
|
||||
{
|
||||
foundText = str;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
foundText = "";
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ContainsOneOf(string textToSearch, IEnumerable<string> strings)
|
||||
{
|
||||
return ContainsOneOf(textToSearch, strings, out _);
|
||||
}
|
||||
|
||||
public static string FormatSize(long bytes)
|
||||
{
|
||||
var i = Math.Abs(bytes) / 1024D;
|
||||
if (i < 1)
|
||||
{
|
||||
return bytes + " B";
|
||||
}
|
||||
else if (i / 1024D < 1)
|
||||
{
|
||||
return i.Round(2) + " KB";
|
||||
}
|
||||
else if (i / (1024D * 1024D) < 1)
|
||||
{
|
||||
return (i / 1024D).Round(2) + " MB";
|
||||
}
|
||||
else
|
||||
{
|
||||
return (i / (1024D * 1024D)).Round(2) + " GB";
|
||||
}
|
||||
}
|
||||
|
||||
private static double Round(this double d, int decimals)
|
||||
{
|
||||
return Math.Round(d, decimals);
|
||||
}
|
||||
|
||||
public static string ReplaceEnd(string input, string substringToReplace, string newSubstring)
|
||||
{
|
||||
int lastIndexOfSubstring = input.LastIndexOf(substringToReplace);
|
||||
if (lastIndexOfSubstring >= 0)
|
||||
{
|
||||
input = input.Remove(lastIndexOfSubstring, substringToReplace.Length)
|
||||
.Insert(lastIndexOfSubstring, newSubstring);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
public static string ConvertCamelCaseToSpaces(string input)
|
||||
{
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
||||
foreach (char c in input)
|
||||
{
|
||||
if (char.IsUpper(c))
|
||||
{
|
||||
output.Append(' ');
|
||||
}
|
||||
|
||||
output.Append(c);
|
||||
}
|
||||
|
||||
return output.ToString().Trim();
|
||||
}
|
||||
|
||||
public static string FormatUptime(double uptime)
|
||||
{
|
||||
TimeSpan t = TimeSpan.FromMilliseconds(uptime);
|
||||
|
||||
return FormatUptime(t);
|
||||
}
|
||||
|
||||
public static string FormatUptime(TimeSpan t)
|
||||
{
|
||||
if (t.Days > 0)
|
||||
{
|
||||
return $"{t.Days}d {t.Hours}h {t.Minutes}m {t.Seconds}s";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"{t.Hours}h {t.Minutes}m {t.Seconds}s";
|
||||
}
|
||||
}
|
||||
|
||||
public static string FormatDate(DateTime e)
|
||||
{
|
||||
string i2s(int i)
|
||||
{
|
||||
if (i.ToString().Length < 2)
|
||||
return "0" + i;
|
||||
return i.ToString();
|
||||
}
|
||||
|
||||
return $"{i2s(e.Day)}.{i2s(e.Month)}.{e.Year} {i2s(e.Hour)}:{i2s(e.Minute)}";
|
||||
}
|
||||
|
||||
public static string FormatDateOnly(DateTime e)
|
||||
{
|
||||
string i2s(int i)
|
||||
{
|
||||
if (i.ToString().Length < 2)
|
||||
return "0" + i;
|
||||
return i.ToString();
|
||||
}
|
||||
|
||||
return $"{i2s(e.Day)}.{i2s(e.Month)}.{e.Year}";
|
||||
}
|
||||
|
||||
public static string FormatSize(double bytes)
|
||||
{
|
||||
var i = Math.Abs(bytes) / 1024D;
|
||||
if (i < 1)
|
||||
{
|
||||
return bytes + " B";
|
||||
}
|
||||
else if (i / 1024D < 1)
|
||||
{
|
||||
return i.Round(2) + " KB";
|
||||
}
|
||||
else if (i / (1024D * 1024D) < 1)
|
||||
{
|
||||
return (i / 1024D).Round(2) + " MB";
|
||||
}
|
||||
else
|
||||
{
|
||||
return (i / (1024D * 1024D)).Round(2) + " GB";
|
||||
}
|
||||
}
|
||||
|
||||
public static RenderFragment FormatLineBreaks(string content)
|
||||
{
|
||||
return builder =>
|
||||
{
|
||||
int i = 0;
|
||||
var arr = content.Split("\n");
|
||||
|
||||
foreach (var line in arr)
|
||||
{
|
||||
builder.AddContent(i, line);
|
||||
if (i++ != arr.Length - 1)
|
||||
{
|
||||
builder.AddMarkupContent(i, "<br/>");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static string FormatAgoFromDateTime(DateTime dt)
|
||||
{
|
||||
TimeSpan timeSince = DateTime.UtcNow.Subtract(dt);
|
||||
|
||||
if (timeSince.TotalMilliseconds < 1)
|
||||
return "just now";
|
||||
|
||||
if (timeSince.TotalMinutes < 1)
|
||||
return "less than a minute ago";
|
||||
|
||||
if (timeSince.TotalMinutes < 2)
|
||||
return "1 minute ago";
|
||||
|
||||
if (timeSince.TotalMinutes < 60)
|
||||
return Math.Round(timeSince.TotalMinutes) + " minutes ago";
|
||||
|
||||
if (timeSince.TotalHours < 2)
|
||||
return "1 hour ago";
|
||||
|
||||
if (timeSince.TotalHours < 24)
|
||||
return Math.Round(timeSince.TotalHours) + " hours ago";
|
||||
|
||||
if (timeSince.TotalDays < 2)
|
||||
return "1 day ago";
|
||||
|
||||
return Math.Round(timeSince.TotalDays) + " days ago";
|
||||
}
|
||||
|
||||
// This will replace every placeholder with the respective value if specified in the model
|
||||
// For example:
|
||||
// A instance of the user model has been passed in the 'models' parameter of the function.
|
||||
// So the placeholder {{User.Email}} will be replaced by the value of the Email property of the model
|
||||
public static string ProcessTemplating(string text, params object[] models)
|
||||
{
|
||||
foreach (var model in models)
|
||||
{
|
||||
foreach (var property in model.GetType().GetProperties())
|
||||
{
|
||||
var value = property.GetValue(model);
|
||||
|
||||
if(value == null)
|
||||
continue;
|
||||
|
||||
var placeholder = "{{" + $"{model.GetType().Name}.{property.Name}" + "}}";
|
||||
|
||||
text = text.Replace(placeholder, value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
using System.Security.Cryptography;
|
||||
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
// Src: https://codereview.stackexchange.com/questions/176697/net-core-mvc-future-proof-hashing-of-passwords
|
||||
public static class HashHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// The default number of Iterations
|
||||
/// </summary>
|
||||
private const int DefaultIterations = 10000;
|
||||
|
||||
/// <summary>
|
||||
/// Provides Information about a specific Hash Version
|
||||
/// </summary>
|
||||
private class HashVersion
|
||||
{
|
||||
public short Version { get; set; }
|
||||
public int SaltSize { get; set; }
|
||||
public int HashSize { get; set; }
|
||||
public KeyDerivationPrf KeyDerivation { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Holds all possible Hash Versions
|
||||
/// </summary>
|
||||
private static readonly Dictionary<short, HashVersion> _versions = new Dictionary<short, HashVersion>
|
||||
{
|
||||
{
|
||||
1, new HashVersion
|
||||
{
|
||||
Version = 1,
|
||||
KeyDerivation = KeyDerivationPrf.HMACSHA512,
|
||||
HashSize = 256 / 8,
|
||||
SaltSize = 128 / 8
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The default Hash Version, which should be used, if a new Hash is Created
|
||||
/// </summary>
|
||||
private static HashVersion DefaultVersion => _versions[1];
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a given hash uses the latest version
|
||||
/// </summary>
|
||||
/// <param name="data">The hash</param>
|
||||
/// <returns>Is the hash of the latest version?</returns>
|
||||
public static bool IsLatestHashVersion(byte[] data)
|
||||
{
|
||||
var version = BitConverter.ToInt16(data, 0);
|
||||
return version == DefaultVersion.Version;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a given hash uses the latest version
|
||||
/// </summary>
|
||||
/// <param name="data">The hash</param>
|
||||
/// <returns>Is the hash of the latest version?</returns>
|
||||
public static bool IsLatestHashVersion(string data)
|
||||
{
|
||||
var dataBytes = Convert.FromBase64String(data);
|
||||
return IsLatestHashVersion(dataBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a random byte array
|
||||
/// </summary>
|
||||
/// <param name="length">The length of the byte array</param>
|
||||
/// <returns>The random byte array</returns>
|
||||
public static byte[] GetRandomBytes(int length)
|
||||
{
|
||||
var data = new byte[length];
|
||||
using (var randomNumberGenerator = RandomNumberGenerator.Create())
|
||||
{
|
||||
randomNumberGenerator.GetBytes(data);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Hash of a clear text
|
||||
/// </summary>
|
||||
/// <param name="clearText">the clear text</param>
|
||||
/// <param name="iterations">the number of iteration the hash alogrythm should run</param>
|
||||
/// <returns>the Hash</returns>
|
||||
public static byte[] Hash(string clearText, int iterations = DefaultIterations)
|
||||
{
|
||||
//get current version
|
||||
var currentVersion = DefaultVersion;
|
||||
|
||||
//get the byte arrays of the hash and meta information
|
||||
var saltBytes = GetRandomBytes(currentVersion.SaltSize);
|
||||
var versionBytes = BitConverter.GetBytes(currentVersion.Version);
|
||||
var iterationBytes = BitConverter.GetBytes(iterations);
|
||||
var hashBytes = KeyDerivation.Pbkdf2(clearText, saltBytes, currentVersion.KeyDerivation, iterations,
|
||||
currentVersion.HashSize);
|
||||
|
||||
//calculate the indexes for the combined hash
|
||||
var indexVersion = 0;
|
||||
var indexIteration = indexVersion + 2;
|
||||
var indexSalt = indexIteration + 4;
|
||||
var indexHash = indexSalt + currentVersion.SaltSize;
|
||||
|
||||
//combine all data to one result hash
|
||||
var resultBytes = new byte[2 + 4 + currentVersion.SaltSize + currentVersion.HashSize];
|
||||
Array.Copy(versionBytes, 0, resultBytes, indexVersion, 2);
|
||||
Array.Copy(iterationBytes, 0, resultBytes, indexIteration, 4);
|
||||
Array.Copy(saltBytes, 0, resultBytes, indexSalt, currentVersion.SaltSize);
|
||||
Array.Copy(hashBytes, 0, resultBytes, indexHash, currentVersion.HashSize);
|
||||
return resultBytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Hash of a clear text and convert it to a Base64 String representation
|
||||
/// </summary>
|
||||
/// <param name="clearText">the clear text</param>
|
||||
/// <param name="iterations">the number of iteration the hash alogrythm should run</param>
|
||||
/// <returns>the Hash</returns>
|
||||
public static string HashToString(string clearText, int iterations = DefaultIterations)
|
||||
{
|
||||
var data = Hash(clearText, iterations);
|
||||
return Convert.ToBase64String(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies a given clear Text against a hash
|
||||
/// </summary>
|
||||
/// <param name="clearText">The clear text</param>
|
||||
/// <param name="data">The hash</param>
|
||||
/// <returns>Is the hash equal to the clear text?</returns>
|
||||
public static bool Verify(string clearText, byte[] data)
|
||||
{
|
||||
//Get the current version and number of iterations
|
||||
var currentVersion = _versions[BitConverter.ToInt16(data, 0)];
|
||||
var iteration = BitConverter.ToInt32(data, 2);
|
||||
|
||||
//Create the byte arrays for the salt and hash
|
||||
var saltBytes = new byte[currentVersion.SaltSize];
|
||||
var hashBytes = new byte[currentVersion.HashSize];
|
||||
|
||||
//Calculate the indexes of the salt and the hash
|
||||
var indexSalt = 2 + 4; // Int16 (Version) and Int32 (Iteration)
|
||||
var indexHash = indexSalt + currentVersion.SaltSize;
|
||||
|
||||
//Fill the byte arrays with salt and hash
|
||||
Array.Copy(data, indexSalt, saltBytes, 0, currentVersion.SaltSize);
|
||||
Array.Copy(data, indexHash, hashBytes, 0, currentVersion.HashSize);
|
||||
|
||||
//Hash the current clearText with the parameters given via the data
|
||||
var verificationHashBytes = KeyDerivation.Pbkdf2(clearText, saltBytes, currentVersion.KeyDerivation, iteration,
|
||||
currentVersion.HashSize);
|
||||
|
||||
//Check if generated hashes are equal
|
||||
return hashBytes.SequenceEqual(verificationHashBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies a given clear Text against a hash
|
||||
/// </summary>
|
||||
/// <param name="clearText">The clear text</param>
|
||||
/// <param name="data">The hash</param>
|
||||
/// <returns>Is the hash equal to the clear text?</returns>
|
||||
public static bool Verify(string clearText, string data)
|
||||
{
|
||||
var dataBytes = Convert.FromBase64String(data);
|
||||
return Verify(clearText, dataBytes);
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
namespace Moonlight.App.Helpers.LogMigrator;
|
||||
|
||||
public class LogMigrateProvider : ILoggerProvider
|
||||
{
|
||||
public void Dispose() {}
|
||||
|
||||
public ILogger CreateLogger(string categoryName)
|
||||
{
|
||||
return new MigrateLogger();
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
namespace Moonlight.App.Helpers.LogMigrator;
|
||||
|
||||
public class MigrateLogger : ILogger
|
||||
{
|
||||
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null;
|
||||
|
||||
public bool IsEnabled(LogLevel logLevel)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
|
||||
{
|
||||
switch (logLevel)
|
||||
{
|
||||
case LogLevel.Critical:
|
||||
Logger.Fatal(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Fatal(exception);
|
||||
|
||||
break;
|
||||
case LogLevel.Warning:
|
||||
Logger.Warn(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Warn(exception);
|
||||
|
||||
break;
|
||||
case LogLevel.Debug:
|
||||
Logger.Debug(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Debug(exception);
|
||||
|
||||
break;
|
||||
case LogLevel.Error:
|
||||
Logger.Error(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Error(exception);
|
||||
|
||||
break;
|
||||
case LogLevel.Information:
|
||||
Logger.Info(formatter(state, exception));
|
||||
|
||||
if(exception != null)
|
||||
Logger.Info(exception);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using Serilog;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public class Logger
|
||||
{
|
||||
#region String logger
|
||||
public static void Verbose(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Verbose("{Message}", message);
|
||||
}
|
||||
|
||||
public static void Info(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Information("{Message}", message);
|
||||
}
|
||||
|
||||
public static void Debug(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Debug("{Message}", message);
|
||||
}
|
||||
|
||||
public static void Error(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Error("{Message}", message);
|
||||
}
|
||||
|
||||
public static void Warn(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Warning("{Message}", message);
|
||||
}
|
||||
|
||||
public static void Fatal(string message, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Fatal("{Message}", message);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Exception method calls
|
||||
|
||||
public static void Verbose(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Verbose(exception, "");
|
||||
}
|
||||
|
||||
public static void Info(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Information(exception, "");
|
||||
}
|
||||
|
||||
public static void Debug(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Debug(exception, "");
|
||||
}
|
||||
|
||||
public static void Error(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Error(exception, "");
|
||||
}
|
||||
|
||||
public static void Warn(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Warning(exception, "");
|
||||
}
|
||||
|
||||
public static void Fatal(Exception exception, string channel = "default")
|
||||
{
|
||||
Log.ForContext("SourceContext", GetNameOfCallingClass())
|
||||
.Fatal(exception, "");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static string GetNameOfCallingClass(int skipFrames = 4)
|
||||
{
|
||||
string fullName;
|
||||
Type declaringType;
|
||||
|
||||
do
|
||||
{
|
||||
MethodBase method = new StackFrame(skipFrames, false).GetMethod();
|
||||
declaringType = method.DeclaringType;
|
||||
if (declaringType == null)
|
||||
{
|
||||
return method.Name;
|
||||
}
|
||||
|
||||
skipFrames++;
|
||||
if (declaringType.Name.Contains("<"))
|
||||
fullName = declaringType.ReflectedType.Name;
|
||||
else
|
||||
fullName = declaringType.Name;
|
||||
} while (declaringType.Module.Name.Equals("mscorlib.dll", StringComparison.OrdinalIgnoreCase) |
|
||||
fullName.Contains("Logger"));
|
||||
|
||||
return fullName;
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public static class PathBuilder
|
||||
{
|
||||
public static string Dir(params string[] parts)
|
||||
{
|
||||
var res = "";
|
||||
|
||||
foreach (var part in parts)
|
||||
{
|
||||
res += part + Path.DirectorySeparatorChar;
|
||||
}
|
||||
|
||||
return res.Replace(
|
||||
$"{Path.DirectorySeparatorChar}{Path.DirectorySeparatorChar}",
|
||||
$"{Path.DirectorySeparatorChar}"
|
||||
);
|
||||
}
|
||||
|
||||
public static string File(params string[] parts)
|
||||
{
|
||||
var res = "";
|
||||
|
||||
foreach (var part in parts)
|
||||
{
|
||||
res += part + (part == parts.Last() ? "" : Path.DirectorySeparatorChar);
|
||||
}
|
||||
|
||||
return res.Replace(
|
||||
$"{Path.DirectorySeparatorChar}{Path.DirectorySeparatorChar}",
|
||||
$"{Path.DirectorySeparatorChar}"
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
using System.Reflection;
|
||||
|
||||
namespace Moonlight.App.Helpers;
|
||||
|
||||
public class PropBinder<T>
|
||||
{
|
||||
private PropertyInfo PropertyInfo;
|
||||
private object DataObject;
|
||||
|
||||
public PropBinder(PropertyInfo propertyInfo, object dataObject)
|
||||
{
|
||||
PropertyInfo = propertyInfo;
|
||||
DataObject = dataObject;
|
||||
}
|
||||
|
||||
public string StringValue
|
||||
{
|
||||
get => (string)PropertyInfo.GetValue(DataObject)!;
|
||||
set => PropertyInfo.SetValue(DataObject, value);
|
||||
}
|
||||
|
||||
public int IntValue
|
||||
{
|
||||
get => (int)PropertyInfo.GetValue(DataObject)!;
|
||||
set => PropertyInfo.SetValue(DataObject, value);
|
||||
}
|
||||
|
||||
public long LongValue
|
||||
{
|
||||
get => (long)PropertyInfo.GetValue(DataObject)!;
|
||||
set => PropertyInfo.SetValue(DataObject, value);
|
||||
}
|
||||
|
||||
public bool BoolValue
|
||||
{
|
||||
get => (bool)PropertyInfo.GetValue(DataObject)!;
|
||||
set => PropertyInfo.SetValue(DataObject, value);
|
||||
}
|
||||
|
||||
public DateTime DateTimeValue
|
||||
{
|
||||
get => (DateTime)PropertyInfo.GetValue(DataObject)!;
|
||||
set => PropertyInfo.SetValue(DataObject, value);
|
||||
}
|
||||
|
||||
public T Class
|
||||
{
|
||||
get => (T)PropertyInfo.GetValue(DataObject)!;
|
||||
set => PropertyInfo.SetValue(DataObject, value);
|
||||
}
|
||||
|
||||
public double DoubleValue
|
||||
{
|
||||
get => (double)PropertyInfo.GetValue(DataObject)!;
|
||||
set => PropertyInfo.SetValue(DataObject, value);
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Models.Enums;
|
||||
using Moonlight.App.Repositories;
|
||||
using Moonlight.App.Services;
|
||||
using Moonlight.App.Services.Utils;
|
||||
|
||||
namespace Moonlight.App.Http.Controllers.Api.Auth;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/auth/reset")]
|
||||
public class ResetController : Controller
|
||||
{
|
||||
private readonly Repository<User> UserRepository;
|
||||
private readonly IdentityService IdentityService;
|
||||
private readonly JwtService JwtService;
|
||||
|
||||
public ResetController(Repository<User> userRepository, IdentityService identityService, JwtService jwtService)
|
||||
{
|
||||
UserRepository = userRepository;
|
||||
IdentityService = identityService;
|
||||
JwtService = jwtService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ActionResult> Get([FromQuery] string token)
|
||||
{
|
||||
// Validate token
|
||||
|
||||
if (!await JwtService.Validate(token))
|
||||
return Redirect("/password-reset");
|
||||
|
||||
var data = await JwtService.Decode(token);
|
||||
|
||||
if (!data.ContainsKey("accountToReset"))
|
||||
return Redirect("/password-reset");
|
||||
|
||||
var userId = int.Parse(data["accountToReset"]);
|
||||
var user = UserRepository
|
||||
.Get()
|
||||
.FirstOrDefault(x => x.Id == userId);
|
||||
|
||||
// User may have been deleted, so we check here
|
||||
|
||||
if (user == null)
|
||||
return Redirect("/password-reset");
|
||||
|
||||
// In order to allow the user to get access to the change password screen
|
||||
// we need to authenticate him so we can read his flags.
|
||||
// That's why we are creating a session here
|
||||
|
||||
var sessionToken = await IdentityService.GenerateToken(user);
|
||||
|
||||
// Authenticate the current identity service instance in order to
|
||||
// get access to the flags field.
|
||||
await IdentityService.Authenticate(sessionToken);
|
||||
IdentityService.Flags[UserFlag.PasswordPending] = true;
|
||||
await IdentityService.SaveFlags();
|
||||
|
||||
// Make the user login so he can reach the change password screen
|
||||
Response.Cookies.Append("token", sessionToken);
|
||||
return Redirect("/");
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.App.Helpers;
|
||||
using Moonlight.App.Models.Enums;
|
||||
using Moonlight.App.Services;
|
||||
using Moonlight.App.Services.Utils;
|
||||
|
||||
namespace Moonlight.App.Http.Controllers.Api.Auth;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/auth/verify")]
|
||||
public class VerifyController : Controller
|
||||
{
|
||||
private readonly IdentityService IdentityService;
|
||||
private readonly JwtService JwtService;
|
||||
|
||||
public VerifyController(IdentityService identityService, JwtService jwtService)
|
||||
{
|
||||
IdentityService = identityService;
|
||||
JwtService = jwtService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ActionResult> Get([FromQuery] string token)
|
||||
{
|
||||
await IdentityService.Authenticate(Request);
|
||||
|
||||
if (!IdentityService.IsSignedIn)
|
||||
return Redirect("/login");
|
||||
|
||||
if (!await JwtService.Validate(token))
|
||||
return Redirect("/login");
|
||||
|
||||
var data = await JwtService.Decode(token);
|
||||
|
||||
if (!data.ContainsKey("mailToVerify"))
|
||||
return Redirect("/login");
|
||||
|
||||
var mailToVerify = data["mailToVerify"];
|
||||
|
||||
if (mailToVerify != IdentityService.CurrentUser.Email)
|
||||
{
|
||||
Logger.Warn($"User {IdentityService.CurrentUser.Email} tried to mail verify {mailToVerify} via verify api endpoint", "security");
|
||||
return Redirect("/login");
|
||||
}
|
||||
|
||||
IdentityService.Flags[UserFlag.MailVerified] = true;
|
||||
await IdentityService.SaveFlags();
|
||||
|
||||
return Redirect("/");
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.App.Helpers;
|
||||
using Moonlight.App.Services;
|
||||
|
||||
namespace Moonlight.App.Http.Controllers.Api;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/bucket")]
|
||||
public class BucketController : Controller
|
||||
{
|
||||
private readonly BucketService BucketService;
|
||||
|
||||
public BucketController(BucketService bucketService)
|
||||
{
|
||||
BucketService = bucketService;
|
||||
}
|
||||
|
||||
[HttpGet("{bucket}/{file}")]
|
||||
public async Task<ActionResult> Get([FromRoute] string bucket, [FromRoute] string file) // TODO: Implement auth
|
||||
{
|
||||
if (bucket.Contains("..") || file.Contains(".."))
|
||||
{
|
||||
Logger.Warn($"Detected path transversal attack ({Request.HttpContext.Connection.RemoteIpAddress}).", "security");
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var stream = await BucketService.Pull(bucket, file);
|
||||
return File(stream, MimeTypes.GetMimeType(file));
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moonlight.App.Api;
|
||||
|
||||
namespace Moonlight.App.Http.Controllers.Api;
|
||||
|
||||
public class WebsocketController : Controller
|
||||
{
|
||||
private readonly ApiManagementService ApiManagementService;
|
||||
|
||||
public WebsocketController(ApiManagementService apiManagementService)
|
||||
{
|
||||
ApiManagementService = apiManagementService;
|
||||
}
|
||||
|
||||
[Route("/api/ws")]
|
||||
public async Task Get()
|
||||
{
|
||||
if (HttpContext.WebSockets.IsWebSocketRequest)
|
||||
{
|
||||
using (var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync())
|
||||
{
|
||||
await Echo(webSocket);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Echo(WebSocket webSocket)
|
||||
{
|
||||
var context = new ApiUserContext(webSocket);
|
||||
ApiManagementService.Contexts.Add(context);
|
||||
|
||||
await webSocket.SendAsync(Encoding.UTF8.GetBytes("Hello World"), WebSocketMessageType.Text,
|
||||
true, CancellationToken.None);
|
||||
|
||||
try
|
||||
{
|
||||
while (webSocket.State == WebSocketState.Open)
|
||||
{
|
||||
var buffer = new byte[1024 * 10];
|
||||
var data = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||
buffer = buffer[..data.Count];
|
||||
|
||||
await ApiManagementService.HandleRequest(context, buffer);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ApiManagementService.Contexts.Remove(context);
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
using Moonlight.App.Models.Enums;
|
||||
|
||||
namespace Moonlight.App.Models.Abstractions;
|
||||
|
||||
public class FlagStorage
|
||||
{
|
||||
private readonly List<string> FlagList;
|
||||
|
||||
public UserFlag[] Flags => FlagList
|
||||
.Select(x => Enum.Parse(typeof(UserFlag), x))
|
||||
.Select(x => (UserFlag)x)
|
||||
.ToArray();
|
||||
|
||||
public string[] RawFlags => FlagList.ToArray();
|
||||
public string RawFlagString => string.Join(";", FlagList);
|
||||
|
||||
public bool this[UserFlag flag]
|
||||
{
|
||||
get => Flags.Contains(flag);
|
||||
set => Set(flag.ToString(), value);
|
||||
}
|
||||
|
||||
public bool this[string flagName]
|
||||
{
|
||||
get => FlagList.Contains(flagName);
|
||||
set => Set(flagName, value);
|
||||
}
|
||||
|
||||
public FlagStorage(string flagString)
|
||||
{
|
||||
FlagList = flagString
|
||||
.Split(";")
|
||||
.Where(x => !string.IsNullOrEmpty(x))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public void Set(string flagName, bool shouldAdd)
|
||||
{
|
||||
if (shouldAdd)
|
||||
{
|
||||
if(!FlagList.Contains(flagName))
|
||||
FlagList.Add(flagName);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FlagList.Contains(flagName))
|
||||
FlagList.Remove(flagName);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
namespace Moonlight.App.Models.Abstractions;
|
||||
|
||||
public abstract class PaymentGateway
|
||||
{
|
||||
public abstract string Name { get; }
|
||||
public abstract string Icon { get; }
|
||||
public abstract Task<string> Start(double price);
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
using Moonlight.App.Models.Enums;
|
||||
|
||||
namespace Moonlight.App.Models.Abstractions;
|
||||
|
||||
public class PermissionStorage
|
||||
{
|
||||
public readonly int PermissionInteger;
|
||||
|
||||
public PermissionStorage(int permissionInteger)
|
||||
{
|
||||
PermissionInteger = permissionInteger;
|
||||
}
|
||||
|
||||
public Permission[] Permissions => GetPermissions();
|
||||
|
||||
public Permission[] GetPermissions()
|
||||
{
|
||||
return GetAllPermissions()
|
||||
.Where(x => (int)x <= PermissionInteger)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public static Permission[] GetAllPermissions()
|
||||
{
|
||||
return Enum.GetValues<Permission>();
|
||||
}
|
||||
|
||||
public static Permission GetFromInteger(int id)
|
||||
{
|
||||
return GetAllPermissions().First(x => (int)x == id);
|
||||
}
|
||||
|
||||
public bool this[Permission permission] => Permissions.Contains(permission);
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
using Moonlight.App.Database.Entities.Store;
|
||||
|
||||
namespace Moonlight.App.Models.Abstractions;
|
||||
|
||||
public abstract class ServiceActions
|
||||
{
|
||||
public abstract Task Create(IServiceProvider provider, Service service);
|
||||
public abstract Task Update(IServiceProvider provider, Service service);
|
||||
public abstract Task Delete(IServiceProvider provider, Service service);
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
using Moonlight.App.Database.Entities;
|
||||
|
||||
namespace Moonlight.App.Models.Abstractions;
|
||||
|
||||
public class Session
|
||||
{
|
||||
public string Ip { get; set; } = "N/A";
|
||||
public string Url { get; set; } = "N/A";
|
||||
public User? User { get; set; }
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; // To remove inactive sessions
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
namespace Moonlight.App.Models.Abstractions;
|
||||
|
||||
public class Subscriber
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public object Action { get; set; }
|
||||
public object Handle { get; set; }
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
namespace Moonlight.App.Models.Enums;
|
||||
|
||||
public enum Permission
|
||||
{
|
||||
Default = 0,
|
||||
AdminMenu = 999,
|
||||
AdminOverview = 1000,
|
||||
AdminUsers = 1001,
|
||||
AdminSessions = 1002,
|
||||
AdminUsersEdit = 1003,
|
||||
AdminTickets = 1004,
|
||||
AdminCommunity = 1030,
|
||||
AdminStore = 1900,
|
||||
AdminViewExceptions = 1999,
|
||||
AdminRoot = 2000
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
namespace Moonlight.App.Models.Enums;
|
||||
|
||||
public enum UserFlag
|
||||
{
|
||||
MailVerified,
|
||||
PasswordPending,
|
||||
TotpEnabled
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Moonlight.App.Models.Forms.Admin.Community;
|
||||
|
||||
public class AddWordFilter
|
||||
{
|
||||
[Required(ErrorMessage = "You need to specify a filter")]
|
||||
[Description(
|
||||
"This filters all posts and comments created using this regex. If any match is found it will block the action")]
|
||||
public string Filter { get; set; } = "";
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Moonlight.App.Models.Forms.Admin.Community;
|
||||
|
||||
public class EditWordFilter
|
||||
{
|
||||
[Required(ErrorMessage = "You need to specify a filter")]
|
||||
[Description(
|
||||
"This filters all posts and comments created using this regex. If any match is found it will block the action")]
|
||||
public string Filter { get; set; } = "";
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Moonlight.App.Models.Forms.Admin.Store;
|
||||
|
||||
public class AddCouponForm
|
||||
{
|
||||
[MinLength(5, ErrorMessage = "The code needs to be longer than 4")]
|
||||
[MaxLength(15, ErrorMessage = "The code should not be longer than 15 characters")]
|
||||
public string Code { get; set; } = "";
|
||||
|
||||
[Range(1, 99, ErrorMessage = "The percent needs to be between 1 and 99")]
|
||||
public int Percent { get; set; }
|
||||
|
||||
[Range(0, int.MaxValue, ErrorMessage = "The amount needs to be equals or greater than 0")]
|
||||
public int Amount { get; set; }
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Moonlight.App.Models.Forms.Admin.Store;
|
||||
|
||||
public class AddGiftCodeForm
|
||||
{
|
||||
[MinLength(5, ErrorMessage = "The code needs to be longer than 4")]
|
||||
[MaxLength(15, ErrorMessage = "The code should not be longer than 15 characters")]
|
||||
public string Code { get; set; } = "";
|
||||
|
||||
[Range(0, int.MaxValue, ErrorMessage = "The value needs to be equals or greater than 0")]
|
||||
public double Value { get; set; }
|
||||
|
||||
[Range(0, int.MaxValue, ErrorMessage = "The amount needs to be equals or greater than 0")]
|
||||
public int Amount { get; set; }
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Moonlight.App.Models.Forms.Admin.Store;
|
||||
|
||||
public class EditCouponForm
|
||||
{
|
||||
[MinLength(5, ErrorMessage = "The code needs to be longer than 4")]
|
||||
[MaxLength(15, ErrorMessage = "The code should not be longer than 15 characters")]
|
||||
public string Code { get; set; } = "";
|
||||
|
||||
[Range(1, 99, ErrorMessage = "The percent needs to be between 1 and 99")]
|
||||
public int Percent { get; set; }
|
||||
|
||||
[Range(0, int.MaxValue, ErrorMessage = "The amount needs to be equals or greater than 0")]
|
||||
public int Amount { get; set; }
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Moonlight.App.Models.Forms.Admin.Store;
|
||||
|
||||
public class EditGiftCodeForm
|
||||
{
|
||||
[MinLength(5, ErrorMessage = "The code needs to be longer than 4")]
|
||||
[MaxLength(15, ErrorMessage = "The code should not be longer than 15 characters")]
|
||||
public string Code { get; set; } = "";
|
||||
|
||||
[Range(0, int.MaxValue, ErrorMessage = "The value needs to be equals or greater than 0")]
|
||||
public double Value { get; set; }
|
||||
|
||||
[Range(0, int.MaxValue, ErrorMessage = "The amount needs to be equals or greater than 0")]
|
||||
public int Amount { get; set; }
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue