Compare commits

..

200 commits

Author SHA1 Message Date
Masu Baumgartner
a4080cc1b1
Merge pull request #418 from Moonlight-Panel/v2_UpdateToDotnet8
Upgraded moonlight to dotnet 8
2024-05-27 14:32:46 +02:00
Masu Baumgartner
4f5a4913d7 Upgraded moonlight to dotnet 8 2024-05-27 14:32:16 +02:00
Masu Baumgartner
c340e48f02
Merge pull request #415 from Moonlight-Panel/v2_addNodeOnlineCheckOnServerDeploy
Added node online check on server create
2024-05-23 14:37:26 +02:00
Masu Baumgartner
257af8106d
Merge pull request #417 from Moonlight-Panel/v2_ImproveModularUI
Made user dashboard modular and extendable via plugins
2024-05-21 21:50:43 +02:00
Moritz
6eedc8aba9 Renamed the Implementation 2024-05-21 14:12:46 +02:00
Moritz
cba98bdf6f Made Index page Modular
Made Index Page editable with the Plugin System, added greeting Component
2024-05-20 09:07:06 +02:00
Marcel Baumgartner
d2da868b71 Updated to use the new mooncore version 2024-05-19 20:37:54 +02:00
Masu Baumgartner
685221b454
Merge pull request #416 from Moonlight-Panel/v2_ResponsivenessImprovements
Improved responsive behaviour
2024-05-19 15:33:08 +02:00
Moritz
f12e5f10d5 Improved Server Ui responsivity 2024-05-19 15:20:24 +02:00
Moritz
cc7b4d7daa Improved Responsiveness for auth pages 2024-05-19 14:52:42 +02:00
Moritz
769c876dc5 Added a way to sort the admin components with an index 2024-05-19 14:27:45 +02:00
Moritz
ccec79cca7 Added node online check on Server create 2024-05-19 00:04:27 +02:00
Moritz
e79f2199c3
Forgot two stars - readme.md 2024-05-18 23:52:09 +02:00
Moritz
c53d315bd8
Update README.md 2024-05-18 23:51:18 +02:00
Moritz
0ae9c27d93 Removed Last buggy thing
Forgot to remove it :(
2024-05-18 22:17:04 +02:00
Masu Baumgartner
2950034a30
Merge pull request #407 from Moonlight-Panel/v2_ImprovedAdminPage
Improved admin page with extendable columns and components via plugin system
2024-05-18 22:15:06 +02:00
Masu Baumgartner
158115bb3b
Merge branch 'v2' into v2_ImprovedAdminPage 2024-05-18 22:14:05 +02:00
Moritz
56184a8254 Final admin Page
Added Admin System To be as Modular as masu wants it to be
2024-05-18 22:11:58 +02:00
Masu Baumgartner
c27b1689f3
Merge pull request #410 from Moonlight-Panel/v2_AdminPageLinkFix
Fixed Linking and Cards on Admin Page
2024-05-17 08:42:01 +02:00
Moritz
3c3dd2af92
Made issue template v2 ready
Removed Wings Issue field, edited placeholders for version
2024-05-16 16:26:09 +02:00
Moritz
125260e7ef Fixed Linking and Cards on Admin Page 2024-05-16 16:21:39 +02:00
Marcel Baumgartner
b608a0779c Quick-fix for server loading in user view 2024-05-14 21:57:08 +02:00
Moritz
7225db0bf1 added some informations 2024-05-14 14:52:27 +02:00
Masu Baumgartner
3f0cdff262
Merge pull request #408 from Moonlight-Panel/v2_FileManagerImprovements
Adding some more file manager improvements to the main branch
2024-05-14 14:50:10 +02:00
Moritz
3270039a6a improved admin page
Added the logic for a more modular admin page, where every feature can add cards and components with just a call of a function
2024-05-14 14:43:54 +02:00
Marcel Baumgartner
fda972a90e Implemented archiving and extracting for users 2024-05-14 14:08:07 +02:00
Masu Baumgartner
45e81c98bf
Merge pull request #406 from Moonlight-Panel/v2_AddAdminPage
Added Basic Admin Page, will still be adding more in the future
2024-05-14 00:46:27 +02:00
Moritz
d9dd9bbf4d Optimized it, as Masu wished 2024-05-14 00:42:00 +02:00
Moritz
160de6443b Added Basic Admin Page, will still be adding more in the future 2024-05-13 18:38:52 +02:00
Masu Baumgartner
923a3c18b8 Started adding archive ui 2024-05-13 16:20:38 +02:00
Masu Baumgartner
8dc37525ce Improved egg importing so it should be able to import any egg now 2024-05-06 18:34:50 +02:00
Masu Baumgartner
7bd34842fa Commented out dummy value 2024-05-06 10:26:08 +02:00
Masu Baumgartner
da8b01bb98 Added server kill confirmation prompt. Improved power action handling 2024-05-06 10:24:45 +02:00
Masu Baumgartner
c9fe469f5b
Merge pull request #404 from Moonlight-Panel/v2_FileManagerImprovements
Improved file manager. This is the first merge of this branch. More commits are planned
2024-05-06 09:45:54 +02:00
Masu Baumgartner
406f7cad65 Added empty file list indicator. Removed dropzone.js 2024-05-06 09:44:38 +02:00
Masu Baumgartner
558e237608 Small fix for node memory calculation
Made calculation accurate using:
https://stackoverflow.com/questions/41224738/how-to-calculate-system-memory-usage-from-proc-meminfo-like-htop
2024-05-06 09:15:27 +02:00
Marcel Baumgartner
b4251a0f1f Started with adding modules for archiving for the file manager 2024-05-04 23:06:15 +02:00
Marcel Baumgartner
0234a8e179 Increased kestrel default limits and added option to change the moonlight defaults 2024-05-01 20:17:41 +02:00
Masu Baumgartner
efacaa9b86
Merge pull request #402 from Moonlight-Panel/v2_addFaviconWithAssetApi
V2 add favicon with asset api
2024-04-30 09:04:24 +02:00
Moritz
7c40d999ff Image already existed so i used that one 2024-04-29 16:34:11 +02:00
Moritz
99c14693d5 Added Favicon using the asset api 2024-04-29 16:19:54 +02:00
Marcel Baumgartner
2cf03d4b68 Improved MySQL container boot handling
This will reduce the large error messages to a single line saying that the mysql container is still booting. Hopefully this fixes the login cli command as well
2024-04-29 16:16:25 +02:00
Masu Baumgartner
52bab229ea
Add files via upload 2024-04-27 22:29:17 +02:00
Marcel Baumgartner
8b15383b45 Fixed percentage calculation of disk space 2024-04-27 22:05:03 +02:00
Marcel Baumgartner
eaddefdc8e Fixed node overview crash when no cores are available 2024-04-27 21:58:20 +02:00
Marcel Baumgartner
95cfa815fb Added some missing labels for the server manager ui 2024-04-27 17:35:24 +02:00
Marcel Baumgartner
870b2516a1 Fixed node list percentage calculation for storage 2024-04-27 17:03:45 +02:00
Masu Baumgartner
ef982a52ed
Merge pull request #398 from Moonlight-Panel/v2_FixNodeLogsNullRef
Fixed the null reference exception when moonlight is unable to reach the node
2024-04-27 13:49:48 +02:00
Marcel Baumgartner
6ae2390b46 Fixed the null reference exception when moonlight is unable to reach the node 2024-04-27 13:49:15 +02:00
Masu Baumgartner
e1fbf601f3
Merge pull request #397 from Moonlight-Panel/v2_AddDetailsInNodeList
Added more details into the node list (like cpu, memory and disk)
2024-04-27 13:48:03 +02:00
Marcel Baumgartner
2364a53dd1 Added more details into the node list (like cpu, memory and disk) 2024-04-27 13:47:15 +02:00
Marcel Baumgartner
be7cecc721 Added github issue templates and funding.yml file
Thank you @gOOvER  for the templates. Just added them back in from the main branch
2024-04-26 19:08:14 +02:00
Masu Baumgartner
f2aad2ccdf
Merge pull request #395 from Moonlight-Panel/v2_AddNodeLogView
Added node log view
2024-04-23 16:58:55 +02:00
Marcel Baumgartner
8e76a68b62 Added node log view 2024-04-23 16:58:11 +02:00
Masu Baumgartner
6c722a9ac3
Merge pull request #394 from Moonlight-Panel/v2_AddFooterCustomisation
Added footer customization
2024-04-23 16:26:50 +02:00
Marcel Baumgartner
52515e7df1 Added footer customization 2024-04-23 16:26:26 +02:00
Masu Baumgartner
722c56271f
Merge pull request #393 from Moonlight-Panel/v2_SmallUiImprovements
Small ui improvements
2024-04-23 16:04:36 +02:00
Marcel Baumgartner
9e85c35f59 Upgraded to mooncoreui 1.1.6 2024-04-23 16:03:51 +02:00
Marcel Baumgartner
538a15b609 Added new mooncore form attributes for creating servers 2024-04-23 16:03:35 +02:00
Marcel Baumgartner
bb0ab9dc67 Added missing space for tooltip in the settings 2024-04-23 16:03:03 +02:00
Marcel Baumgartner
87b9b5e1c2 Fixed mobile layout for permission integer input 2024-04-23 16:02:43 +02:00
Masu Baumgartner
ba0b46db90
Merge pull request #392 from theghostofakatsuki/v2_AddNodeFqdnValidation
Added validation for the fqdn field of the node
2024-04-23 14:06:44 +02:00
theghostofakatsuki
ddcbf56abe Added validation for the fqdn field of the node 2024-04-23 14:03:35 +02:00
Masu Baumgartner
c553f6f5da
Merge pull request #390 from Moonlight-Panel/v2_AddRegisterDeny
Added the option to disable register
2024-04-22 18:23:48 +02:00
Marcel Baumgartner
5b25774851 Added the option to disable register 2024-04-22 18:23:09 +02:00
Marcel Baumgartner
01729b982d Improved console disposing and closing 2024-04-17 17:03:18 +02:00
Masu Baumgartner
fd01787dfb
Merge pull request #388 from Moonlight-Panel/v2_ImproveConsoleStreaming
Improved console streaming
2024-04-17 15:43:32 +02:00
Marcel Baumgartner
90eed5c74c Fixed a bug. Improved error handling. Small cleanup of code 2024-04-17 15:42:51 +02:00
Marcel Baumgartner
dcfb836b39 Added some documentation
it triggered me that this was missing, okay?
2024-04-17 15:42:23 +02:00
Marcel Baumgartner
610501ef19 Improved console ui disposing 2024-04-17 07:49:48 +02:00
Marcel Baumgartner
48e2e1eb98 Fixed weird console restore glitch 2024-04-17 07:31:56 +02:00
Marcel Baumgartner
f3ad71e33f Switched to improved mooncore advanced websocket stream version 2024-04-16 22:56:42 +02:00
Marcel Baumgartner
eaacdb3446 Fixed memory calculation of moonlight itself 2024-04-16 17:18:40 +02:00
Marcel Baumgartner
be173e1d48 Working on improved console streaming 2024-04-16 07:40:48 +02:00
Marcel Baumgartner
e3f040c978 Added the ability to send commands using the Enter key and not clicking the button
Was about time lol
2024-04-15 18:40:53 +02:00
Marcel Baumgartner
e25b005643 Upgraded to MoonCoreUI 1.1.5. Added allocations needed field for images 2024-04-15 17:39:23 +02:00
Masu Baumgartner
4631e66dca
Merge pull request #387 from Moonlight-Panel/v2_FixImageDelete
Fixed image deletion
2024-04-14 11:58:08 +02:00
Marcel Baumgartner
73b93f8262 Fixed image deletion 2024-04-14 11:56:04 +02:00
Masu Baumgartner
5a1ecebbe9
Merge pull request #384 from gOOvER/name-lengh
Updated all user name length attributes in form models
2024-04-13 00:39:17 +02:00
gOOvER
8dbf458ea3 lot more placews for the Username lengh 2024-04-12 15:13:49 +02:00
Masu Baumgartner
c5fef04d06
Merge pull request #382 from gOOvER/goover
Change username length to 6
2024-04-12 10:42:55 +02:00
Marcel Baumgartner
5fb507febc Handle node booting state in the server console websocket 2024-04-12 10:41:54 +02:00
gOOvER
50d6954829 change username leght to 6 2024-04-12 08:20:44 +02:00
Marcel Baumgartner
e5f4fd9d62 Added auth header for console streaming 2024-04-11 13:07:27 +02:00
Masu Baumgartner
7da87fb065
Merge pull request #380 from Moonlight-Panel/v2_EarlyAccessFixes
Fixed bugs reported by early access people
2024-04-11 08:46:05 +02:00
Marcel Baumgartner
b81646c1d4 Fixed crash when deleting images 2024-04-11 08:41:43 +02:00
Marcel Baumgartner
752f84127c Changed lets encrypt email. Formatted command better 2024-04-10 22:30:43 +02:00
Marcel Baumgartner
bf1b9533c8 Updated node setup url 2024-04-10 12:29:47 +02:00
Masu Baumgartner
feddea1a69
Merge pull request #374 from Moonlight-Panel/v2_FinalizeFileManager
Finalized file manager
2024-04-01 20:32:42 +02:00
Marcel Baumgartner
20fcd5015e Improved file manager, switched to faster node/daemon file communication. Removed old components 2024-04-01 17:04:38 +02:00
Marcel Baumgartner
9abf32b288 Added select folder dialog. Added item moving as a module 2024-03-30 23:47:59 +01:00
Marcel Baumgartner
5d9c32a196 Added file editor to the api. Made the entire file manager available to the interfaces. 2024-03-30 22:39:28 +01:00
Marcel Baumgartner
cdc2954d0b Implemented modular create actions 2024-03-30 22:26:52 +01:00
Marcel Baumgartner
b2929fe211 Added modular selection actions 2024-03-30 22:06:33 +01:00
Marcel Baumgartner
3a74f3abcd Fixed small mistake on native ssl support 2024-03-30 00:21:33 +01:00
Marcel Baumgartner
49077e7023 Reimplemented the file manager with a cleaner ui, a base path protection from the core and modular and expandable 2024-03-30 00:18:40 +01:00
Marcel Baumgartner
44b2d07fdb Moved logo assets to the core asset folder. Removed unused default avatar 2024-03-24 21:16:21 +01:00
Marcel Baumgartner
0ee4f3fe04 Replaced io usage with network usage in stats page 2024-03-24 21:09:54 +01:00
Marcel Baumgartner
456d87f262 Added http debug middleware to trace requests 2024-03-24 19:20:13 +01:00
Marcel Baumgartner
e47a4c29f7 Switched to mooncore log rotation. Added experimental https support 2024-03-24 12:48:50 +01:00
Marcel Baumgartner
f172d765e3 Started adding node setup page 2024-03-22 20:50:11 +01:00
Marcel Baumgartner
9bf129f1ad Added automatic user creation on first start 2024-03-19 17:31:15 +01:00
Marcel Baumgartner
1cb603a3f3 Added default assets to docker image 2024-03-19 17:30:58 +01:00
Marcel Baumgartner
0a807605ad New v2 project structure 2024-03-18 09:31:33 +01:00
Marcel Baumgartner
e20415a5bd New gitignore 2024-03-18 09:31:13 +01:00
Marcel Baumgartner
15a3789174 Remove old v2 structure 2024-03-18 09:30:30 +01:00
Masu Baumgartner
823970f617
Merge pull request #372 from Moonlight-Panel/v2_ServerFeature
V2 server feature
2024-03-18 09:27:23 +01:00
Masu Baumgartner
5a025eb75b
Create README.md 2024-03-04 11:17:17 +01:00
Marcel Baumgartner
bf6641c151 Reimplemented config in diagnose file and added node data 2024-02-14 12:07:14 +01:00
Marcel Baumgartner
f18877f9b1 Small ui fix 2024-02-14 11:46:05 +01:00
Marcel Baumgartner
c3679afed7 Fixed debug log config 2024-02-14 10:34:05 +01:00
Marcel Baumgartner
a0ca9af5c9 Started implementing schedules feature 2024-02-14 10:20:04 +01:00
Marcel Baumgartner
d1f73e6d78 Added reconnecting animation instead of connection lost icon for connection indicator 2024-02-13 22:56:18 +01:00
Marcel Baumgartner
368886c95c Removed console border 2024-02-13 22:52:46 +01:00
Marcel Baumgartner
86f3957028 Adjusted some font styles for server view 2024-02-13 22:50:37 +01:00
Marcel Baumgartner
6ec86fdc25 Improved ux for ticket popup 2024-02-13 22:46:31 +01:00
Marcel Baumgartner
068858f3a1 Added spacing to server user layout navbar 2024-02-13 22:33:06 +01:00
Marcel Baumgartner
8d11d2360e Redesigned network tab 2024-02-13 22:32:49 +01:00
Marcel Baumgartner
970bca7121 Fixed input alignment for variable page 2024-02-11 17:57:16 +01:00
Marcel Baumgartner
07c09e48e3 Started adding network tab for servers 2024-02-11 17:54:15 +01:00
Marcel Baumgartner
b2c816cafb Added console page as default page 2024-02-11 16:41:20 +01:00
Marcel Baumgartner
960a0bceff Reduced server console initial content 2024-02-11 16:38:51 +01:00
Marcel Baumgartner
aaf4c05630 Fixed moving items to the location they are currently at 2024-02-11 16:38:28 +01:00
Marcel Baumgartner
fada1a11b0 Added docker image select / variable editor page 2024-02-07 22:30:51 +01:00
Marcel Baumgartner
dfa34a6808 Fixed variable loading for single server query 2024-02-07 22:30:10 +01:00
Marcel Baumgartner
1b427607d1 Fixed jwt validation error. Added node allocations editor. Small fixes 2024-02-07 21:08:37 +01:00
Marcel Baumgartner
70445069fd Fixed docker build and ensured a storage folder is created to mount to volume to 2024-02-07 21:07:38 +01:00
Marcel Baumgartner
423616b9f3 Implemented download in the file manager. Made file access jwt more modular 2024-02-06 22:23:47 +01:00
Marcel Baumgartner
26ed50c94b Refactored and cleaned some stuff 2024-02-06 19:30:30 +01:00
Marcel Baumgartner
caa34dd79d Reimplemented filemanager and fixed some bugs 2024-02-06 11:12:04 +01:00
Marcel Baumgartner
0eabe27196 Reimplementing file manager and code editor (untested)
TODO: Add ftp auth back
2024-02-05 22:40:15 +01:00
Marcel Baumgartner
dfc2b5af17 Added hotkey service. Modified jwt service to use jwt types 2024-02-05 22:39:09 +01:00
Marcel Baumgartner
955946d0a6 Implemented console. Fixed streaming bugs. Added server command sending. Added reset and router back 2024-02-03 12:18:06 +01:00
Marcel Baumgartner
9e515d9ed7 Added state streaming. Started working on server console 2024-02-02 22:21:31 +01:00
Marcel Baumgartner
95507fd41f Added database migration checking and fixed/mocked server layout 2024-02-01 22:43:43 +01:00
Marcel Baumgartner
8d75b30ae4 Finished switching to mooncore 2024-02-01 17:56:05 +01:00
Marcel Baumgartner
64bcfe74e7 Refactored whole solution to use the MoonCore and MoonCoreUI library 2024-02-01 14:57:10 +01:00
Marcel Baumgartner
2729564495 Moved service admin pages to correct folder 2024-01-31 12:13:57 +01:00
Marcel Baumgartner
0ec6949095 Started updating service feature with missing changes from AddServersFeature branch 2024-01-30 22:56:26 +01:00
Marcel Baumgartner
681403ec6e Fixed some bugs and added a error handler for the service creation 2024-01-30 22:42:07 +01:00
Marcel Baumgartner
aaee81e9c4 Improved image editor and added more options 2024-01-29 17:17:42 +01:00
Marcel Baumgartner
4e5124cc1b Added image update pages. Added forms models. Implemented parts of the image editor components 2024-01-28 17:50:20 +01:00
Marcel Baumgartner
99a7d7bd73 Started implementing image editor and parse config editor 2024-01-28 13:58:23 +01:00
Marcel Baumgartner
6fd1336f1c Added base models for servers. Added ws packet connection utility. Added some ui from old branch. Added some packeges. And more smaller things 2024-01-27 13:28:09 +01:00
Marcel Baumgartner
33c1ffa0ba Started reimplementing server feature because we use a new project structure now. This is way cleaner than the last implementation 2024-01-26 20:09:53 +01:00
Marcel Baumgartner
19001e5836
Merge pull request #362 from Moonlight-Panel/v2_RestructureTry2
Restructured whole v2 project to be easier to develop new features
2024-01-26 17:02:30 +01:00
Marcel Baumgartner
12bc66a95b Restructured the rest of the features to their own environment 2024-01-26 13:53:34 +01:00
Marcel Baumgartner
63b2b40227 After the first try literally gave me a head ace, there is the second try with a better way of structuring it and not divinding so much core components in individual features. Still not done though 2024-01-25 21:40:23 +01:00
Marcel Baumgartner
bb53f1c40a
Merge pull request #359 from Moonlight-Panel/v2_TransactionImprovement
Implemented transaction dates
2024-01-19 10:34:33 +01:00
Marcel Baumgartner
46f08059d7 Implemented transaction dates 2024-01-19 10:34:01 +01:00
Marcel Baumgartner
a9af1ec15e
Merge pull request #358 from Moonlight-Panel/v2_UiFixes
Added some ui fixes
2024-01-16 16:32:14 +01:00
Marcel Baumgartner
9179d6825c Improved order duration border effect 2024-01-16 16:30:44 +01:00
Marcel Baumgartner
4816befa71 Improved ticket popup button. Added better separation between tickets in the user view 2024-01-16 16:25:34 +01:00
Marcel Baumgartner
67c846ddc8 Renamed announcements to news in community navigation 2024-01-16 16:18:38 +01:00
Marcel Baumgartner
79d860351c Resized profile picture change text in user settings 2024-01-16 16:15:09 +01:00
Marcel Baumgartner
c1216ea708 Improved 2fa and password ui 2024-01-16 16:12:36 +01:00
Marcel Baumgartner
a11569a737 Fixed inconsistent spacing. Reduced page size for transactions 2024-01-16 16:03:52 +01:00
Marcel Baumgartner
cd4feec58f Made space for more diagnose components 2024-01-16 16:02:01 +01:00
Marcel Baumgartner
518ec7055a Removed inconsistent border in settings/configuration page 2024-01-16 15:57:39 +01:00
Marcel Baumgartner
2552b92e5d Improved user dashboard 2024-01-16 15:38:28 +01:00
Marcel Baumgartner
e9d3ab5307 Added error reporting in soft error handler 2024-01-16 15:02:15 +01:00
Marcel Baumgartner
becc67c46b Improved error message view of soft error handler 2024-01-16 14:59:44 +01:00
Marcel Baumgartner
c3a0833410 Improved error view of smart form 2024-01-16 14:56:10 +01:00
Marcel Baumgartner
da53a0eef7
Merge pull request #357 from Moonlight-Panel/v2_AddEnvironmentConfiguration
Implemented environment variable loading in config service
2024-01-16 14:39:14 +01:00
Marcel Baumgartner
289f8921ff Implemented environment variable loading in config service 2024-01-16 14:38:43 +01:00
Marcel Baumgartner
e1a0cfeebb Merge branch 'v2' of https://github.com/Moonlight-Panel/Moonlight into v2 2024-01-08 08:43:29 +01:00
Marcel Baumgartner
55a7d71c7f Improved error message for username regex on register form 2024-01-08 08:43:11 +01:00
Marcel Baumgartner
8d1cb47a8a
Merge pull request #353 from Moonlight-Panel/v2_ImproveTicketing
Improved ticketing
2024-01-08 08:34:39 +01:00
Marcel Baumgartner
2510d6748c Implemented viewing of closed tickets for users 2024-01-08 08:32:57 +01:00
Marcel Baumgartner
f17ff9246d Implemented input disable on closed tickets for users 2024-01-08 08:32:39 +01:00
Marcel Baumgartner
a2a9a6e21d
Merge pull request #352 from Moonlight-Panel/v2_AntiAdBlocker
Implemented basic adblocker prevention
2024-01-05 11:44:18 +01:00
Marcel Baumgartner
0e1ddfbccb Implemented basic adblocker prevention
Tested with uBlockOrigin
2024-01-05 11:43:37 +01:00
Marcel Baumgartner
2edf8b4a9f
Merge pull request #351 from Moonlight-Panel/v2_Fixes
Some fixes
2024-01-05 11:06:10 +01:00
Marcel Baumgartner
e47cac71fc Added a proper error message when starting a charge process without selecting a payment gateway 2024-01-05 11:05:35 +01:00
Marcel Baumgartner
0aa28d9764 Fixed service renewal check to allow admins to access the service even if it is expired 2024-01-05 11:04:43 +01:00
Marcel Baumgartner
8b032462c0
Merge pull request #350 from Moonlight-Panel/v2_AddDiagnoseFileExport
Added diagnose file export
2024-01-04 16:04:28 +01:00
Marcel Baumgartner
3ae694a3da Added diagnose file export 2024-01-04 16:03:55 +01:00
Marcel Baumgartner
741d13b18a Changed invalid img sources 2023-12-22 23:09:58 +01:00
Marcel Baumgartner
0d8cc5bd5d
Merge pull request #345 from Moonlight-Panel/v2_AddThemeFeature
Added theme feature
2023-12-22 23:03:29 +01:00
Marcel Baumgartner
04ef9dc827 Added asset proxy. Adding google fonts as file instead of loading it externally. Removed demo theme 2023-12-22 23:02:37 +01:00
Marcel Baumgartner
c11ff632d2 Implemented theme exporting and importing 2023-12-22 20:47:00 +01:00
Marcel Baumgartner
c5a3c0550c As the default theme is not shown in the Themes page, we do not need this way of checking if its enabled 2023-12-22 14:38:08 +01:00
Marcel Baumgartner
a67829035e Implemented basic theme feature. Missing are import, export and asset proxy 2023-12-22 14:27:37 +01:00
Marcel Baumgartner
f57aac4f6c Made some ui changes 2023-11-18 23:25:52 +01:00
Marcel Baumgartner
3a53fa0a3c Done some todo's and removed old TL tags 2023-11-16 00:48:06 +01:00
Marcel Baumgartner
7145890801
Merge pull request #338 from Moonlight-Panel/AddServiceImplementationApi
Added service implementation api and some service utils
2023-11-15 21:06:02 +01:00
Marcel Baumgartner
6d5a5fd16c Added expired services overview to store pages 2023-11-15 21:02:35 +01:00
Baumgartner Marcel
3092daaad4 Fixed cookie loading. Started implementing service expire handling 2023-11-15 15:24:27 +01:00
Baumgartner Marcel
0f989a38c3 Implemented service admin view 2023-11-15 11:05:12 +01:00
Baumgartner Marcel
e8706cad1c Made implementation api cleaner 2023-11-15 10:25:28 +01:00
Baumgartner Marcel
d55490dd51 Started working on service implementation api 2023-11-14 17:54:15 +01:00
Marcel Baumgartner
a1cd6b5cd9
Merge pull request #337 from Moonlight-Panel/AddTicketSystem
Added ticket system
2023-11-10 15:14:49 +01:00
Marcel Baumgartner
0e43278bdd
Merge branch 'v2' into AddTicketSystem 2023-11-10 15:13:51 +01:00
Marcel Baumgartner
d8bb2b7356 Implemented bucket delete and improved avatar update 2023-11-10 15:10:09 +01:00
Marcel Baumgartner
f779e5e920 Added logo and favicon 2023-11-09 21:47:11 +01:00
Marcel Baumgartner
c57ad9cce7 Fixed ui bugs. Implemented ticket deletion when a user is going to be deleted 2023-11-09 14:42:41 +01:00
Marcel Baumgartner
b492d65efb Added details in ticket view. Renamed mail verify button 2023-11-09 14:09:23 +01:00
Marcel Baumgartner
332937f964 Started implementing admin ticket ui. Cleaned up some stuff 2023-11-09 01:56:14 +01:00
Marcel Baumgartner
f5501f77fe Implemented file upload and improved ui. Fixed file upload bug in ticket service 2023-11-06 17:41:24 +01:00
Marcel Baumgartner
1c96f9d13c Started implementing the ticket system. Implemented user site tickets without attachments atm. Added db models 2023-11-01 17:35:12 +01:00
677 changed files with 22525 additions and 13944 deletions

8
.gitattributes vendored
View file

@ -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
View file

@ -0,0 +1,2 @@
# These are supported funding model platforms
ko_fi: masuowo

87
.github/ISSUE_TEMPLATE/bug-report.yml vendored Normal file
View 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
View 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.

View 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
View file

@ -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
View 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
View 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>

View file

@ -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>

View file

@ -1,13 +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" />
</map>
</option>
</component>
</project>

View 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>

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderProjectSettingsUpdater">
<option name="vcsConfiguration" value="2" />
</component>
</project>

View file

@ -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
View 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.

View file

@ -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

26
Moonlight/App.razor Normal file
View 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>

View file

@ -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;
}
}

View file

@ -1,117 +0,0 @@
using System.ComponentModel;
using AngleSharp.Dom;
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();
[JsonProperty("Discord")] public DiscordData Discord { 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;
}
public class DiscordData
{
[JsonProperty("Bot")] public BotData Bot { get; set; } = new();
[JsonProperty("WebHook")] public WebHookData WebHook { get; set; } = new();
public class BotData
{
[JsonProperty("Enable")]
[Description("Sets if the Bot is enabeled or not")]
public bool Enable { get; set; } = false;
[JsonProperty("Token")]
[Description("Set here your Bot Token. Get one here https://discord.dev")]
public string Token { get; set; } = "Token here";
[JsonProperty("GuildId")]
[Description("Set here your Discord Guild Id")]
public long GuildId { get; set; }
[JsonProperty("LoggingId")]
[Description("This must be a PostChannel Recomended use: /setup")]
public long PostChannelId { get; set; }
[JsonProperty("ThreadChannels")]
[Description("This is reqired for Logging Don't Touch")]
public List<long>? PostIds { get; set; }
}
public class WebHookData
{
[JsonProperty("Enable")]
[Description("Sets if the WebHook features are enabeled or not")]
public bool Enable { get; set; } = false;
[JsonProperty("WebHook")]
[Description("")]
public string WebHook { get; set; } = "https://discord.dev/";
}
}
}

View file

@ -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)
);
}
}
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

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

View file

@ -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; } = "";
}

View file

@ -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; }
}

View file

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

View file

@ -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; }
}

View file

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

View file

@ -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;
}

View file

@ -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;
}

View file

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

View file

@ -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; } = "";
}

View file

@ -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;
}

View file

@ -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; }
}

View file

@ -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;
}

View file

@ -1,8 +0,0 @@
namespace Moonlight.App.Database.Enums;
public enum PostType
{
Project = 0,
Announcement = 1,
Event = 2
}

View file

@ -1,9 +0,0 @@
namespace Moonlight.App.Database.Enums;
public enum ServiceType
{
Server,
Webspace,
Database,
Domain
}

View file

@ -1,9 +0,0 @@
namespace Moonlight.App.Database.Enums;
public enum TicketPriority
{
Low,
Medium,
High,
Critical
}

View file

@ -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
}
}
}

View file

@ -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");
}
}
}

View file

@ -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
}
}
}

View file

@ -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");
}
}
}

View file

@ -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
}
}
}

View file

@ -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");
}
}
}

View file

@ -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
}
}
}

View file

@ -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");
}
}
}

View file

@ -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
}
}
}

View file

@ -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");
}
}
}

View file

@ -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
}
}
}

View file

@ -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");
}
}
}

View file

@ -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
}
}
}

View file

@ -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; }
}

View file

@ -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; }
}

View file

@ -1,23 +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;
public static EventHandler OnMoonlightRestart;
}

View file

@ -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)
{
}
}

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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();
};
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -1,11 +0,0 @@
namespace Moonlight.App.Helpers.LogMigrator;
public class LogMigrateProvider : ILoggerProvider
{
public void Dispose() {}
public ILogger CreateLogger(string categoryName)
{
return new MigrateLogger();
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}

View file

@ -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}"
);
}
}

View file

@ -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);
}
}

View file

@ -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("/");
}
}

View file

@ -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("/");
}
}

View file

@ -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();
}
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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
}

View file

@ -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; }
}

View file

@ -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
}

View file

@ -1,8 +0,0 @@
namespace Moonlight.App.Models.Enums;
public enum UserFlag
{
MailVerified,
PasswordPending,
TotpEnabled
}

View file

@ -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; } = "";
}

View file

@ -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; } = "";
}

View file

@ -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; }
}

View file

@ -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; }
}

View file

@ -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; }
}

View file

@ -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; }
}

View file

@ -1,16 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.App.Models.Forms.Admin.Users;
public class UpdateUserForm
{
[Required(ErrorMessage = "You need to enter a username")]
[MinLength(7, ErrorMessage = "The username is too short")]
[MaxLength(20, ErrorMessage = "The username cannot be longer than 20 characters")]
[RegularExpression("^[a-z][a-z0-9]*$", ErrorMessage = "Usernames can only contain lowercase characters and numbers")]
public string Username { get; set; } = "";
[Required(ErrorMessage = "You need to enter a email address")]
[EmailAddress(ErrorMessage = "You need to enter a valid email address")]
public string Email { get; set; } = "";
}

View file

@ -1,11 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.App.Models.Forms.Admin.Users;
public class UpdateUserPasswordForm
{
[Required(ErrorMessage = "You need to specify a password")]
[MinLength(8, ErrorMessage = "The password must be at least 8 characters long")]
[MaxLength(256, ErrorMessage = "The password must not be longer than 256 characters")]
public string Password { get; set; } = "";
}

View file

@ -1,10 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.App.Models.Forms.Auth;
public class ResetPasswordForm
{
[Required(ErrorMessage = "You need to specify an email address")]
[EmailAddress(ErrorMessage = "You need to enter a valid email address")]
public string Email { get; set; } = "";
}

View file

@ -1,9 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.App.Models.Forms.Auth;
public class TwoFactorCodeForm
{
[Required(ErrorMessage = "You need to enter a two factor code")]
public string Code { get; set; } = "";
}

View file

@ -1,16 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.App.Models.Forms.Auth;
public class UpdateAccountPasswordForm
{
[Required(ErrorMessage = "You need to specify a password")]
[MinLength(8, ErrorMessage = "The password must be at least 8 characters long")]
[MaxLength(256, ErrorMessage = "The password must not be longer than 256 characters")]
public string Password { get; set; } = "";
[Required(ErrorMessage = "You need to repeat your new password")]
[MinLength(8, ErrorMessage = "The password must be at least 8 characters long")]
[MaxLength(256, ErrorMessage = "The password must not be longer than 256 characters")]
public string RepeatedPassword { get; set; } = "";
}

View file

@ -1,16 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.App.Models.Forms.Community;
public class AddPostForm
{
[Required(ErrorMessage = "You need to enter a title")]
[MaxLength(40, ErrorMessage = "The title can only be 40 characters long")]
[MinLength(8, ErrorMessage = "The title must at least have 8 characters")]
public string Title { get; set; } = "";
[Required(ErrorMessage = "You need to enter post content")]
[MaxLength(2048, ErrorMessage = "The post content can only be 2048 characters long")]
[MinLength(8, ErrorMessage = "The post content must at least have 8 characters")]
public string Content { get; set; } = "";
}

View file

@ -1,13 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.App.Models.Forms.Services;
public class AddUserToServiceForm
{
[Required(ErrorMessage = "You need to provide an username")]
[MinLength(7, ErrorMessage = "The username is too short")]
[MaxLength(20, ErrorMessage = "The username cannot be longer than 20 characters")]
[RegularExpression("^[a-z][a-z0-9]*$",
ErrorMessage = "Usernames can only contain lowercase characters and numbers")]
public string Username { get; set; } = "";
}

View file

@ -1,15 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.App.Models.Forms.Store;
public class AddCategoryForm
{
[Required(ErrorMessage = "You need to specify a name")]
public string Name { get; set; } = "";
public string Description { get; set; } = "";
[Required(ErrorMessage = "You need to specify a slug")]
[RegularExpression("^[a-z0-9-]+$", ErrorMessage = "You need to enter a valid slug only containing lowercase characters and numbers")]
public string Slug { get; set; } = "";
}

View file

@ -1,40 +0,0 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Moonlight.App.Database.Entities.Store;
using Moonlight.App.Database.Enums;
using Moonlight.App.Extensions.Attributes;
namespace Moonlight.App.Models.Forms.Store;
public class AddProductForm
{
[Required(ErrorMessage = "You need to specify a category")]
[Selector(DisplayProp = "Name", SelectorProp = "Name", UseDropdown = true)]
public Category Category { get; set; }
[Required(ErrorMessage = "You need to specify a name")]
[Description("Teeeeeeeeeeeeeeeeeeeeeeeeeest")]
public string Name { get; set; } = "";
[Required(ErrorMessage = "You need to specify a description")]
public string Description { get; set; } = "";
[Required(ErrorMessage = "You need to specify a slug")]
[RegularExpression("^[a-z0-9-]+$", ErrorMessage = "You need to enter a valid slug only containing lowercase characters and numbers")]
public string Slug { get; set; } = "";
[Range(0, double.MaxValue, ErrorMessage = "The price needs to be equals or greater than 0")]
public double Price { get; set; }
[Range(0, double.MaxValue, ErrorMessage = "The stock needs to be equals or greater than 0")]
public int Stock { get; set; }
[Range(0, double.MaxValue, ErrorMessage = "The max per user amount needs to be equals or greater than 0")]
public int MaxPerUser { get; set; }
[Range(0, double.MaxValue, ErrorMessage = "The duration needs to be equals or greater than 0")]
public int Duration { get; set; }
public ServiceType Type { get; set; }
public string ConfigJson { get; set; } = "{}";
}

View file

@ -1,15 +0,0 @@
using System.ComponentModel.DataAnnotations;
namespace Moonlight.App.Models.Forms.Store;
public class EditCategoryForm
{
[Required(ErrorMessage = "You need to specify a name")]
public string Name { get; set; } = "";
public string Description { get; set; } = "";
[Required(ErrorMessage = "You need to specify a slug")]
[RegularExpression("^[a-z0-9-]+$", ErrorMessage = "You need to enter a valid slug only containing lowercase characters and numbers")]
public string Slug { get; set; } = "";
}

View file

@ -1,36 +0,0 @@
using System.ComponentModel.DataAnnotations;
using Moonlight.App.Database.Entities.Store;
using Moonlight.App.Database.Enums;
namespace Moonlight.App.Models.Forms.Store;
public class EditProductForm
{
[Required(ErrorMessage = "You need to specify a category")]
public Category Category { get; set; }
[Required(ErrorMessage = "You need to specify a name")]
public string Name { get; set; } = "";
[Required(ErrorMessage = "You need to specify a description")]
public string Description { get; set; } = "";
[Required(ErrorMessage = "You need to specify a slug")]
[RegularExpression("^[a-z0-9-]+$", ErrorMessage = "You need to enter a valid slug only containing lowercase characters and numbers")]
public string Slug { get; set; } = "";
[Range(0, double.MaxValue, ErrorMessage = "The price needs to be equals or above 0")]
public double Price { get; set; }
[Range(0, double.MaxValue, ErrorMessage = "The stock needs to be equals or above 0")]
public int Stock { get; set; }
[Range(0, double.MaxValue, ErrorMessage = "The max per user amount needs to be equals or above 0")]
public int MaxPerUser { get; set; }
[Range(0, double.MaxValue, ErrorMessage = "The duration needs to be equals or above 0")]
public int Duration { get; set; }
public ServiceType Type { get; set; }
public string ConfigJson { get; set; } = "{}";
}

View file

@ -1,6 +0,0 @@
namespace Moonlight.App.Models.Templates;
public class MailVerify
{
public string Url { get; set; } = "";
}

View file

@ -1,6 +0,0 @@
namespace Moonlight.App.Models.Templates;
public class ResetPassword
{
public string Url { get; set; } = "";
}

View file

@ -1,12 +0,0 @@
namespace Moonlight.App.Plugins.Contexts;
public class PluginContext
{
public IServiceCollection Services { get; set; }
public IServiceProvider Provider { get; set; }
public IServiceScope Scope { get; set; }
public WebApplicationBuilder WebApplicationBuilder { get; set; }
public WebApplication WebApplication { get; set; }
public List<Action> PreInitTasks = new();
public List<Action> PostInitTasks = new();
}

View file

@ -1,10 +0,0 @@
using Moonlight.App.Plugins.Contexts;
namespace Moonlight.App.Plugins;
public abstract class MoonlightPlugin
{
public PluginContext Context { get; set; }
public abstract Task Enable();
public abstract Task Disable();
}

View file

@ -1,53 +0,0 @@
using Moonlight.App.Database.Entities;
using Moonlight.App.Database.Entities.Store;
using Moonlight.App.Event;
using Moonlight.App.Event.Args;
namespace Moonlight.App.Services.Background;
public class AutoMailSendService // This service is responsible for sending mails automatically
{
private readonly MailService MailService;
public AutoMailSendService(MailService mailService)
{
MailService = mailService;
Events.OnUserRegistered += OnUserRegistered;
Events.OnServiceOrdered += OnServiceOrdered;
Events.OnTransactionCreated += OnTransactionCreated;
}
private async void OnTransactionCreated(object? sender, TransactionCreatedEventArgs eventArgs)
{
await MailService.Send(
eventArgs.User,
"New transaction",
"transactionCreated",
eventArgs.Transaction,
eventArgs.User
);
}
private async void OnServiceOrdered(object? _, Service service)
{
await MailService.Send(
service.Owner,
"New product ordered",
"serviceOrdered",
service,
service.Product,
service.Owner
);
}
private async void OnUserRegistered(object? _, User user)
{
await MailService.Send(
user,
$"Welcome {user.Username}",
"welcome",
user
);
}
}

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