Init Commit

This commit is contained in:
2025-06-16 17:04:55 -07:00
commit d21315cf32
43 changed files with 3089 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
[*.cs]
csharp_new_line_before_open_brace = none
csharp_new_line_before_catch = false
csharp_new_line_before_finally = false
Executable
+11
View File
@@ -0,0 +1,11 @@
Stripe_Key=
MySQL_Server=mistox-database
MySQL_User=root
MySQL_Database=mistox
MySQL_Pass=oasv34$8gpv023dd # Random value for the server and MySQL to communicate with
Email_Server= # Hostname of email server
Email_Port= # SMTP port used
Email_Address= # Email Address to send from
Email_Password= # Password for the email address
Executable
+6
View File
@@ -0,0 +1,6 @@
**/bin
**/obj
.git
.env
.vscode
data
Executable
+26
View File
@@ -0,0 +1,26 @@
# Build
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
# Copy all projects
COPY ["src", "."]
# Restore the Server
RUN dotnet restore 'MistoxWebsite.Server/MistoxWebsite.Server.csproj'
# Publish
FROM build as publish
RUN dotnet publish 'MistoxWebsite.Server/MistoxWebsite.Server.csproj' -c Release -o /app/publish
# Run the app
FROM mcr.microsoft.com/dotnet/aspnet:9.0
ENV ASPNETCORE_HTTP_PORTS=5001
ENV StripeKey=null
ENV MySQLServer=null
ENV MySQLUser=null
ENV MySQLPass=null
ENV MySQLDatabase=Mistox
EXPOSE 5001
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MistoxWebsite.Server.dll"]
+37
View File
@@ -0,0 +1,37 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.002.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MistoxWebsite.Client", "src\MistoxWebsite.Client\MistoxWebsite.Client.csproj", "{9E4D64F9-2F56-4AC5-85CE-51EFEE1513C0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MistoxWebsite.Server", "src\MistoxWebsite.Server\MistoxWebsite.Server.csproj", "{76F2B6C1-FF9A-4BD8-AB7A-7456E8122C44}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MistoxWebsite.Shared", "src\MistoxWebsite.Shared\MistoxWebsite.Shared.csproj", "{19C67017-8C26-439B-95B3-FE346D1AC7D5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9E4D64F9-2F56-4AC5-85CE-51EFEE1513C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9E4D64F9-2F56-4AC5-85CE-51EFEE1513C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9E4D64F9-2F56-4AC5-85CE-51EFEE1513C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E4D64F9-2F56-4AC5-85CE-51EFEE1513C0}.Release|Any CPU.Build.0 = Release|Any CPU
{76F2B6C1-FF9A-4BD8-AB7A-7456E8122C44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{76F2B6C1-FF9A-4BD8-AB7A-7456E8122C44}.Debug|Any CPU.Build.0 = Debug|Any CPU
{76F2B6C1-FF9A-4BD8-AB7A-7456E8122C44}.Release|Any CPU.ActiveCfg = Release|Any CPU
{76F2B6C1-FF9A-4BD8-AB7A-7456E8122C44}.Release|Any CPU.Build.0 = Release|Any CPU
{19C67017-8C26-439B-95B3-FE346D1AC7D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{19C67017-8C26-439B-95B3-FE346D1AC7D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19C67017-8C26-439B-95B3-FE346D1AC7D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19C67017-8C26-439B-95B3-FE346D1AC7D5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B413876B-4048-47F1-B8B8-B974DF5E9E2A}
EndGlobalSection
EndGlobal
Executable
+27
View File
@@ -0,0 +1,27 @@
Fix stripe payments *Updated API*
Havent Tested
After a new account is created notify a user that they need to verify their email before logging in
Cleanup SQL queries
On page load for example there are 4 different queries
AccountInventory.cs
SetInventory isnt fully implimented
ProjectMistData.cs
Data inside the sql doesnt match what is inside the database
ForgotPassword Email / Resetpassword Email
Needs styles that match the theme of the website
Manage / Data tabs in Account settings
Theme needs to be updated to match
Delete button doesn't shade when mouse hovers
frame that comes up isnt themed either
Store Catalog
Add to cart wraps text when screen is too small
Program
Probably need to turn on cors at some point
+8
View File
@@ -0,0 +1,8 @@
FROM mysql
ENV MYSQL_DATABASE=mistox
ENV MYSQL_ROOT_PASSWORD=90pa8pav89h4g08hads
ADD mistox.sql /docker-entrypoint-initdb.d
EXPOSE 3306
+104
View File
@@ -0,0 +1,104 @@
CREATE DATABASE IF NOT EXISTS `mistox`;
USE `mistox`;
CREATE TABLE IF NOT EXISTS `Account` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`UserName` varchar(60) DEFAULT NULL,
`Email` varchar(60) DEFAULT NULL,
`EmailVerified` tinyint(4) DEFAULT NULL,
`PasswordHash` varchar(100) DEFAULT NULL,
PRIMARY KEY (`ID`)
) AUTO_INCREMENT=1;
CREATE TABLE IF NOT EXISTS `AccountInventory` (
`AccountID` int(11) NOT NULL,
`ProductID` int(11) NOT NULL,
`Item` varchar(45) NOT NULL,
`Quantity` int(11) DEFAULT NULL,
`Stats` varchar(45) DEFAULT NULL,
PRIMARY KEY (`AccountID`,`ProductID`,`Item`)
);
CREATE TABLE IF NOT EXISTS `Product` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(45) DEFAULT NULL,
`Description` text DEFAULT NULL,
`Images` longtext DEFAULT NULL,
`Cost` int(11) DEFAULT NULL,
`URL` varchar(200) DEFAULT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `ID_UNIQUE` (`ID`)
) AUTO_INCREMENT=1;
CREATE TABLE IF NOT EXISTS `Cart` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`AccountID` int(11) DEFAULT NULL,
`ProductID` int(11) DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `AccountID` (`AccountID`),
KEY `ProductID` (`ProductID`),
CONSTRAINT `Cart_ibfk_1` FOREIGN KEY (`AccountID`) REFERENCES `Account` (`ID`),
CONSTRAINT `Cart_ibfk_2` FOREIGN KEY (`ProductID`) REFERENCES `Product` (`ID`)
) AUTO_INCREMENT=1;
CREATE TABLE IF NOT EXISTS `ProjectMistData` (
`AccountID` int(11) NOT NULL,
`Credits` int(11) DEFAULT NULL,
`OddballTimer` double DEFAULT NULL,
`SessionToken` varchar(45) DEFAULT NULL,
`SessionID` int(11) DEFAULT NULL,
`Kills` int(11) DEFAULT NULL,
`Deaths` int(11) DEFAULT NULL,
PRIMARY KEY (`AccountID`)
);
CREATE TABLE IF NOT EXISTS `Receipt` (
`AccountID` int(11) NOT NULL,
`ProductID` int(11) NOT NULL,
`ReceiptID` varchar(45) NOT NULL,
`LineItem` int(11) NOT NULL,
`Time` datetime DEFAULT NULL,
`TaxAmount` int(11) DEFAULT NULL,
`TotalCost` int(11) DEFAULT NULL,
PRIMARY KEY (`AccountID`,`ProductID`,`ReceiptID`,`LineItem`)
);
CREATE TABLE IF NOT EXISTS `WebsiteData` (
`AccountID` int(11) NOT NULL,
`FailedPasswordLock` tinyint(4) DEFAULT NULL,
`PasswordAttempts` int(11) DEFAULT NULL,
`CurrentPasswordAttempts` int(11) DEFAULT NULL,
`Role` varchar(45) DEFAULT NULL,
`EmailToken` varchar(45) DEFAULT NULL,
PRIMARY KEY (`AccountID`)
);
INSERT INTO Account (
ID,
UserName,
Email,
EmailVerified,
PasswordHash
) VALUES (
'1',
'admin',
'admin@mistox.com',
'1',
''
);
INSERT INTO WebsiteData (
AccountID,
FailedPasswordLock,
PasswordAttempts,
CurrentPasswordAttempts,
Role,
EmailToken
) VALUES (
'1',
'1',
'5',
'0',
'Admin',
''
);
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
# Compile the source
docker build -t mistox-sql ./database
docker build -t mistox-website .
cd ../mistoxnet-tests
# Start the servers
docker compose up -d --force-recreate --remove-orphans
+8
View File
@@ -0,0 +1,8 @@
#!/bin/bash
# Compile the source
docker build -t mistox-sql ./database
docker build -t mistox-website .
# Start the servers
docker compose up -d --force-recreate --remove-orphans
+29
View File
@@ -0,0 +1,29 @@
services:
mistox-server:
container_name: mistox_server
image: mistox-website:latest
restart: always
environment:
- StripeKey=${Stripe_Key}
- MySQLServer=${MySQL_Server}
- MySQLUser=${MySQL_User}
- MySQLPass=${MySQL_Pass}
- MySQLDatabase=${MySQL_Database}
- EmailServer=${Email_Server}
- EmailPort=${Email_Port}
- EmailAddress=${Email_Address}
- EmailPassword=${Email_Password}
ports:
- 5001:5001
depends_on:
- mistox-database
mistox-database:
container_name: mistox_database
image: mistox-sql:latest
restart: always
volumes:
- ./data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: ${MySQL_Pass}
Submodule src/MistoxWebsite.Client added at db1a58746c
@@ -0,0 +1,385 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using MistoxWebsite.Shared;
using System.Security.Claims;
using MistoxWebsite.Server.Services;
using MistoxWebsite.Server.Services.DatabaseService;
using Microsoft.AspNetCore.Authentication.Cookies;
namespace MistoxWebsite.Server.Controllers {
[ApiController]
public class AuthenticationController : ControllerBase {
DatabaseService _accountContext;
EmailService _emailContext;
public AuthenticationController( DatabaseService DatabaseContext, EmailService emailContext ) {
_accountContext = DatabaseContext;
_emailContext = emailContext;
}
// In Account -> References UserName / PasswordHash
// Out Account
[Route( "api/account/login" )]
[HttpPost]
public async Task<ActionResult<Account>> Login( [FromBody] Account request ) {
try {
Account? test = await _accountContext.GetAccount(request.UserName.ToLower());
if( test != null ) {
if( test.EmailVerified == true ) {
if( test.SiteData.FailedPasswordLock ) {
if( test.SiteData.CurrentPasswordAttempts >= test.SiteData.PasswordAttempts ) {
return new Account() { Error = "Too many failed password attempts. Please reset your password" };
}
}
if( BCrypt.Net.BCrypt.Verify( request.PasswordHash, test.PasswordHash ) ) {
test.SiteData.CurrentPasswordAttempts = 0;
await _accountContext.SetAccount( test );
AccountClaims aClaims = await getClaims(test.ID);
List<Claim> claims = new List<Claim>() {
new Claim(ClaimTypes.Name, aClaims.UserName),
new Claim(ClaimTypes.Email, aClaims.Email),
new Claim("emailverified", aClaims.EmailVerified),
new Claim(ClaimTypes.Role, aClaims.Role),
new Claim("LockAccount", aClaims.FailedPasswordLock),
new Claim("ID", test.ID.ToString())
};
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal( new ClaimsIdentity( claims, "Auth" ) ),
new AuthenticationProperties {
ExpiresUtc = DateTime.UtcNow.AddYears(30), // Add 30 years with sliding on
IsPersistent = request.EmailVerified, // Is set from the StayLoggedIn
}
);
return test;
} else {
test.SiteData.CurrentPasswordAttempts += 1;
await _accountContext.SetAccount( test );
return new Account() { Error = "Wrong password" };
}
}else{
await SendVerify(test);
return new Account() { Error = "A new verify email has been sent. \n Note only 1 email send every 5 mintes" };
}
}
return new Account() { Error = "User doesn't exist" };
} catch( Exception ex ) {
return new Account() { Error = ex.Message };
}
}
// In Account -> References UserName / PasswordHash
// Out Account
[Route( "api/account/session" )]
[HttpPost]
public async Task<ActionResult<Account>> LoginSession( [FromBody] Account request ) {
try {
Account? test = await _accountContext.GetAccount(request.UserName.ToLower());
if( test != null ) {
if( request.PasswordHash == test.PasswordHash ) {
return test;
} else {
test.SiteData.CurrentPasswordAttempts += 1;
await _accountContext.SetAccount( test );
return new Account() { Error = "Wrong password" };
}
}
return new Account() { Error = "User doesn't exist" };
} catch( Exception ex ) {
return new Account() { Error = ex.Message };
}
}
// In Account
// Out List<String>
[Route( "api/account/claims" )]
[HttpPost]
public async Task<ActionResult<AccountClaims>> Claims( [FromBody] Account Account ) {
AccountClaims claims = await getClaims(Account.ID);
return claims;
}
async Task<AccountClaims> getClaims( int AccountID ) {
try {
Account? test = await _accountContext.GetAccountByID(AccountID);
if( test != null ) {
AccountClaims aClaims = new AccountClaims() {
UserName = test.UserName,
Email = test.Email,
Role = test.SiteData.Role
};
aClaims.EmailVerified = test.EmailVerified ? "1" : "0";
aClaims.FailedPasswordLock = test.SiteData.FailedPasswordLock ? "1" : "0";
return aClaims;
}
return new AccountClaims();
} catch {
return new AccountClaims();
}
}
// In Account -> Full account
// Out Account
[Route( "api/account/register" )]
[HttpPost]
public async Task<ActionResult<Account>> Register( [FromBody] Account request ) {
try {
if( await _accountContext.GetAccount( request.UserName.ToLower() ) == null ) {
if( await _accountContext.GetAccount( request.Email.ToLower() ) == null ) {
Account? created = new Account(){
UserName = request.UserName.ToLower(),
Email = request.Email.ToLower(),
EmailVerified = false,
PasswordHash = BCrypt.Net.BCrypt.HashPassword(request.PasswordHash),
};
await _accountContext.NewAccount( created );
created = await _accountContext.GetAccount( request.Email.ToLower() );
if( created != null ) {
AccountClaims aClaims = await getClaims(created.ID);
List<Claim> claims = new List<Claim>() {
new Claim(ClaimTypes.Name, aClaims.UserName),
new Claim(ClaimTypes.Email, aClaims.Email),
new Claim("emailverified", aClaims.EmailVerified),
new Claim(ClaimTypes.Role, aClaims.Role),
new Claim("LockAccount", aClaims.FailedPasswordLock)
};
await SendVerify(created);
return created;
}
return new Account() { Error = "Unknown Error" };
} else {
return new Account() { Error = "Email is already in use" };
}
} else {
return new Account() { Error = "UserName is taken" };
}
} catch( Exception ex ) {
Console.WriteLine("Error: " + ex.Message);
return new Account() { Error = ex.Message };
}
}
// In Account -> References UserName / PasswordHash( Current Password ) / Error( New Password )
// Out Bool
[Route( "api/account/changepassword" )]
[HttpPost]
public async Task<ActionResult<bool>> ChangePassword( [FromBody] Account request ) {
try {
Account? test = await _accountContext.GetAccount(request.UserName.ToLower());
if( test != null ) {
if( BCrypt.Net.BCrypt.Verify( request.PasswordHash, test.PasswordHash ) ) {
test.PasswordHash = BCrypt.Net.BCrypt.HashPassword( request.Error );
test.SiteData.CurrentPasswordAttempts = 0;
await _accountContext.SetAccount( test );
return true;
}
}
return false;
} catch {
return false;
}
}
// In Account -> References UserName / SiteData FailedPasswordLock / SiteData.PasswordAttempts
// Out Error String
[Route( "api/account/toggleAccountLock" )]
[HttpPost]
public async Task<ActionResult<string>> ToggleAccountLock( [FromBody] Account request ) {
try {
Account? test = await _accountContext.GetAccount(request.UserName);
if( test != null ) {
test.SiteData.FailedPasswordLock = request.SiteData.FailedPasswordLock;
test.SiteData.CurrentPasswordAttempts = 0;
test.SiteData.PasswordAttempts = request.SiteData.PasswordAttempts;
await _accountContext.SetAccount( test );
return "Account Lock Status Updated";
}
return "Unknown Error Occurred";
} catch( Exception ex ) {
return ex.Message;
}
}
// Out Account -> only if logged in
[Route( "api/account/get" )]
[HttpPost]
public async Task<ActionResult<Account?>> Get() {
try {
if( User.Identity != null && User.Identity.IsAuthenticated ) {
string? email = User.FindFirstValue(ClaimTypes.Email);
if( !string.IsNullOrEmpty( email ) ) {
Account? test = await _accountContext.GetAccount(email);
if( test != null ) {
return test;
}
}
}
return Ok();
} catch {
return Ok();
}
}
// In Null
// Out Null
[Route( "api/account/logout" )]
[HttpPost]
public async Task Logout() {
await HttpContext.SignOutAsync();
}
string Substitue( string message, string subString, string Replacement ) {
for( int i = 0; i < (message.Length - subString.Length); i++ ) {
if( message.Substring( i, subString.Length ) == subString ) {
string before = message.Substring( 0, i );
string after = message.Substring(i + subString.Length );
return before + Replacement + after;
}
}
return message;
}
// In Account -> References UserName
// Out Success bool
[Route( "api/account/sendverifyemail" )]
[HttpPost]
public async Task<ActionResult<string>> SendVerify( [FromBody] Account request ) {
try {
string key = "v" + request.UserName;
// Stop from sending multiple emails quickly
if ( _emailContext._SentEmails.ContainsKey(key) ){
DateTime PreviousSentTime = _emailContext._SentEmails.GetValueOrDefault(key);
if (PreviousSentTime.AddMinutes(5) > DateTime.Now){
return "Cannot sent another verify email until 5 minutes has elapsed ";
}else{
_emailContext._SentEmails.Remove(key);
}
}
Account? test = await _accountContext.GetAccount(request.UserName.ToLower());
if( test != null ) {
test.SiteData.EmailToken = Guid.NewGuid().ToString();
await _accountContext.SetAccount( test );
string EmailContents = EmailService.VerifyEmailEmail;
EmailContents = Substitue( EmailContents, "@UserName", request.UserName );
EmailContents = Substitue( EmailContents, "@UserName", request.UserName );
EmailContents = Substitue( EmailContents, "@VerifyPassword", test.SiteData.EmailToken );
string result = _emailContext.Send( test.Email, EmailService.VerifyEmailSubject, EmailContents );
_emailContext._SentEmails.Add(key, DateTime.Now);
return result;
}
return "Account not found";
} catch (Exception) {
return "The connection couldn't be established to the email server";
}
}
// In Account -> References UserName / Password( EmailToken )
// Out Success bool
[Route( "api/account/verifyemail" )]
[HttpPost]
public async Task<ActionResult<bool>> VerifyEmail( [FromBody] Account request ) {
try {
Account? test = await _accountContext.GetAccount(request.UserName.ToLower());
if( test != null ) {
if( test.SiteData.EmailToken == request.PasswordHash ) {
test.SiteData.EmailToken = "";
test.EmailVerified = true;
await _accountContext.SetAccount( test );
return true;
}
}
return false;
} catch {
return false;
}
}
// In Account -> References Email
// Out Success bool
[Route( "api/account/sendresetpassword" )]
[HttpPost]
public async Task<ActionResult<string>> ResetPassword( [FromBody] Account request ) {
try {
string key = "p" + request.Email.ToLower();
// Stop from sending multiple emails quickly
if ( _emailContext._SentEmails.ContainsKey(key) ){
DateTime PreviousSentTime = _emailContext._SentEmails.GetValueOrDefault(key);
if (PreviousSentTime.AddMinutes(5) > DateTime.Now){
return "Cannot sent another reset requests until 5 minutes has elapsed";
}else{
_emailContext._SentEmails.Remove(key);
}
}
Account? test = await _accountContext.GetAccount(request.Email.ToLower());
if( test != null ) {
test.SiteData.EmailToken = Guid.NewGuid().ToString();
await _accountContext.SetAccount( test );
string EmailContents = EmailService.ResetPasswordEmail;
EmailContents = Substitue( EmailContents, "@UserName", test.UserName );
EmailContents = Substitue( EmailContents, "@UserName", test.UserName );
EmailContents = Substitue( EmailContents, "@ResetPassWord", test.SiteData.EmailToken );
string result = _emailContext.Send( test.Email, EmailService.VerifyEmailSubject, EmailContents );
_emailContext._SentEmails.Add(key, DateTime.Now);
return result;
}
return "Account Not Found";
} catch (Exception) {
return "The connection couldn't be established to the email server";
}
}
// In Account -> References UserName / Password( NewPassword ) / Error( EmailToken )
// Out Success bool
[Route( "api/account/resetpassword" )]
[HttpPost]
public async Task<ActionResult<bool>> ResetPwdVerify( [FromBody] Account request ) {
try {
Account? test = await _accountContext.GetAccount(request.UserName.ToLower());
if( test != null && !string.IsNullOrEmpty(test.SiteData.EmailToken) ) {
if( test.SiteData.EmailToken == request.Error ) {
test.SiteData.CurrentPasswordAttempts = 0;
test.PasswordHash = BCrypt.Net.BCrypt.HashPassword( request.PasswordHash );
await _accountContext.SetAccount( test );
return true;
}
}
return false;
} catch {
return false;
}
}
// In Account -> References UserName / Password( Password ) )
// Out Success bool
[Route( "api/account/delete" )]
[HttpPost]
public async Task<ActionResult<bool>> delete( [FromBody] Account request ) {
try {
Account? test = await _accountContext.GetAccount(request.UserName.ToLower());
if( test != null ) {
if( BCrypt.Net.BCrypt.Verify( request.PasswordHash, test.PasswordHash ) ) {
await _accountContext.DeleteAccount( test );
return true;
}
}
return false;
} catch {
return false;
}
}
}
}
+41
View File
@@ -0,0 +1,41 @@
using MistoxWebsite.Server.Services.DatabaseService;
using System.Security.Claims;
using MistoxWebsite.Shared;
using Microsoft.AspNetCore.Mvc;
namespace MistoxWebsite.Server.Controllers {
[ApiController]
public class PageLoad : ControllerBase {
DatabaseService _databaseService;
public PageLoad( DatabaseService context ) {
_databaseService = context;
}
[Route( "api/pageload" )]
[HttpPost]
public async Task<ActionResult<PageLoadObject>> onPageLoad() {
try {
if( User.Identity != null && User.Identity.IsAuthenticated ) {
string? id = User.FindFirstValue( "ID" );
if( !string.IsNullOrEmpty( id ) ) {
PageLoadObject test = await _databaseService.getPageLoadObject(int.Parse(id));
if (test.user != null){
test.Cart = await _databaseService.GetCart( test.user );
if( test != null ) {
return test;
}
}
}
}
return NotFound();
} catch (Exception e) {
Console.WriteLine(e.ToString());
return NotFound();
}
}
}
}
+117
View File
@@ -0,0 +1,117 @@
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using MistoxWebsite.Server.Controllers.Payment;
using MistoxWebsite.Server.Services.DatabaseService;
using MistoxWebsite.Shared;
using Newtonsoft.Json;
using Stripe;
using Stripe.Climate;
using Stripe.Tax;
namespace MistoxWebsite.Server.Controllers {
[ApiController]
public class PaymentController : ControllerBase {
DatabaseService _databaseService;
public PaymentController( DatabaseService databaseService ) {
_databaseService = databaseService;
}
// Charges
[Route( "api/getCheckoutToken" )]
[HttpPost]
public async Task<string> GetPaymentKey( [FromQuery] string userID ) {
string OrderNumber = Guid.NewGuid().ToString().Substring(0,10);
Shared.Account? acc = await _databaseService.GetAccount(userID);
if (acc != null) {
List<Cart> cart = await _databaseService.GetCart(acc);
IPayment PaymentPlugin = new StripeIntent(_databaseService);
(bool, string) PaymentResponse = await PaymentPlugin.Purchase(OrderNumber, acc, cart);
if (PaymentResponse.Item1) {
return PaymentResponse.Item2;
}
else {
Console.WriteLine("An error has occured in the payment plugin\n\n");
Console.WriteLine(PaymentResponse.Item2);
Console.WriteLine("\n");
return "0";
}
}
return "0";
}
[Route( "/api/payment/response" )]
[HttpPost]
public async Task<IActionResult> paymentWebhook() {
try {
const string endpointSecret = "whsec_HCO7uv2BPIPmUPOiSg9tfwLZul8usCGG";
string body = await new StreamReader(Request.Body).ReadToEndAsync();
Event e = EventUtility.ConstructEvent( body, Request.Headers["Stripe-Signature"], endpointSecret );
if( e.Type == "payment_intent.succeeded" ) {
// Extract Data from payment confirm
PaymentIntent intent = (PaymentIntent)e.Data.Object;
string orderNumber = "";
int userID = 0;
List<int> productIDs = new List<int>();
int subtotal = 0;
int total = 0;
KeyValuePair<string, string>[] y = intent.Metadata.ToArray();
foreach( KeyValuePair<string, string> cur in y ) {
string val = cur.Key;
if( val == "ordernumber" ) {
orderNumber = cur.Value;
} else if( val == "user" ) {
userID = int.Parse( cur.Value );
} else if( val == "products" ) {
string[] products = cur.Value.Split(',');
foreach( string product in products ) {
if ( !string.IsNullOrEmpty(product) ) {
productIDs.Add( Convert.ToInt32( product ) );
}
}
} else if( val == "subtotal" ) {
subtotal = int.Parse( cur.Value );
} else if( val == "total" ) {
total = int.Parse( cur.Value );
}
}
// Clear the cart
Shared.Account account = new Shared.Account{
ID = userID
};
await _databaseService.ClearCart( account );
// Add data to misox receipt
for( int i = 0; i < productIDs.Count; i++ ) {
int product = productIDs[i];
await _databaseService.NewReceipt( new Receipt {
AccountID = userID,
ProductID = product,
ReceiptID = orderNumber,
Time = DateTime.Now,
TaxAmount = total - subtotal,
TotalCost = total,
LineItem = i
} );
}
} else {
Console.WriteLine( "Unhandled event type: {0}", e.Type );
}
return Ok();
} catch( Exception ex ) {
return Content(ex.ToString());
}
}
}
}
@@ -0,0 +1,11 @@
using MistoxWebsite.Shared;
namespace MistoxWebsite.Server.Controllers.Payment {
public interface IPayment {
public Task<(bool, string)> Purchase(string OrderNumber, Account user, List<Cart> cart);
}
}
@@ -0,0 +1,88 @@
using System;
using System.Collections;
using System.Collections.Generic;
using MistoxWebsite.Server.Controllers.Payment;
using MistoxWebsite.Server.Services.DatabaseService;
using MistoxWebsite.Shared;
using Stripe;
using Stripe.Tax;
namespace MistoxWebsite.Server.Controllers {
public class StripeIntent : IPayment {
DatabaseService _databaseService;
public StripeIntent( DatabaseService databaseService ) {
_databaseService = databaseService;
}
public async Task<(bool, string)> Purchase(string OrderNumber, Shared.Account user, List<Cart> cart) {
try {
// build Recipt and calculate Tax
var options = new CalculationCreateOptions {
Currency = "usd",
CustomerDetails = new CalculationCustomerDetailsOptions {
AddressSource = "billing",
},
Expand = new List<string>() { "line_items" },
LineItems = new List<CalculationLineItemOptions>()
};
List<int> prods = new List<int>();
// Add items to receipt
int subtotal = 0;
foreach (Cart items in cart) {
Shared.Product? product = await _databaseService.GetProduct(items.ProductID);
if (product != null) {
prods.Add(product.ID);
if (product != null) {
subtotal += product.Cost;
options.LineItems.Add(new CalculationLineItemOptions {
Amount = product.Cost,
TaxCode = "txcd_10201000", // Tax code for downloadable digital games
Quantity = 1,
Reference = product.Name,
TaxBehavior = "exclusive"
});
}
}
}
var service = new CalculationService();
Calculation result = service.Create(options);
string csv = "";
foreach (int cur in prods) {
csv = csv + cur + ",";
}
// Crate Payment Intent
PaymentIntentCreateOptions paymentIntent = new PaymentIntentCreateOptions() {
Amount = result.AmountTotal,
Currency = "usd",
Metadata = new Dictionary<string, string> {
{ "ordernumber", OrderNumber },
{ "user", user.ID.ToString() },
{ "products", csv },
{ "subtotal", subtotal.ToString() },
{ "total", result.AmountTotal.ToString() }
},
StatementDescriptor = "Mistox.Net #" + OrderNumber
};
PaymentIntentService intentService = new PaymentIntentService();
PaymentIntent x = await intentService.CreateAsync(paymentIntent);
return (true, x.ClientSecret);
} catch(Exception e) {
return (false, e.ToString());
}
}
}
}
+261
View File
@@ -0,0 +1,261 @@
using Microsoft.AspNetCore.Mvc;
using MistoxWebsite.Server.Services.DatabaseService;
using MistoxWebsite.Shared;
using Newtonsoft.Json;
using System.Security.Claims;
using System.Text;
namespace MistoxWebsite.Server.Controllers {
[ApiController]
public class ProductController : ControllerBase {
DatabaseService _databaseService;
public static List<Product> CatalogItems = new List<Product>();
public ProductController( DatabaseService databaseService ) {
_databaseService = databaseService;
}
[Route( "api/cart/get" )]
[HttpPost]
public async Task<List<Cart>> GetCart( [FromBody] Account acc ) {
try {
List<Cart> cart = await _databaseService.GetCart( acc );
return cart;
} catch {
return new List<Cart>();
}
}
[Route( "api/cart/add" )]
[HttpPost]
public async Task AddCart( [FromBody] Cart cart ) {
try {
await _databaseService.AddToCart( cart );
}catch {
}
}
[Route( "api/cart/remove" )]
[HttpPost]
public async Task RemoveCart( [FromBody] Cart cart ) {
try {
await _databaseService.RemoveFromCart( cart );
} catch {
}
}
[Route( "api/cart/clear" )]
[HttpPost]
public async Task ClearCart( [FromBody] Account acc ) {
try {
await _databaseService.ClearCart( acc );
} catch {
}
}
[Route( "api/product/create" )]
[HttpPost]
public async Task<ActionResult<string>> CreateProduct( [FromBody] Product obj ) {
try {
await _databaseService.NewProduct( obj );
await UpdateStore();
return "Success";
} catch {
return "Failed";
}
}
[Route( "api/product/update" )]
[HttpPost]
public async Task<ActionResult<string>> UpdateProduct( [FromBody] Product obj ) {
try {
await _databaseService.UpdateProduct( obj );
await UpdateStore();
return "Success";
} catch {
return "Failed";
}
}
[Route( "api/product/get" )]
[HttpPost]
public ActionResult<Product> GetProduct( [FromBody] Product product ) {
try {
foreach( Product? prod in CatalogItems ) {
if( product.ID == prod.ID ) {
return prod;
}
}
product.ID = -1;
return product;
} catch {
return new Product();
}
}
[Route( "api/product/getall" )]
[HttpPost]
public ActionResult<List<Product>> GetAllProducts() {
try {
return CatalogItems;
} catch {
return new List<Product>();
}
}
[Route( "api/product/getowned" )]
[HttpPost]
public async Task<ActionResult<List<Receipt>>> GetOwnedProduct() {
try {
if( User.Identity != null && User.Identity.IsAuthenticated ) {
string? email = User.FindFirstValue(ClaimTypes.Email);
if( !string.IsNullOrEmpty( email ) ) {
Account? test = await _databaseService.GetAccount(email);
if( test != null ) {
List<Receipt> returned = await _databaseService.GetAllReceipts(test);
return returned;
}
}
}
return new List<Receipt>();
} catch {
return new List<Receipt>();
}
}
DirObj RecursiveBuild( DirObj DirObj, string workingPath, List<ReceiptProduct> purchased ) {
string[] files = Directory.GetFiles(workingPath);
string[] directories = Directory.GetDirectories(workingPath);
List<DirObj> building = new List<DirObj>();
// Get File Names
Parallel.For( 0, files.Length, ( i ) => {
string fileName = files[i].Substring(workingPath.Length, files[i].Length - (workingPath.Length));
building.Add( new DirObj {
Type = FileType.File,
Path = fileName
});
} );
// Get Path Names
Parallel.For( 0, directories.Length, ( i ) => {
foreach( ReceiptProduct cur in purchased ) {
string dirName = directories[i].Substring(workingPath.Length, directories[i].Length - (workingPath.Length));
if( contains( dirName, cur.product.URL ) ) {
DirObj dir = new DirObj {
Type = FileType.Directory,
Path = dirName,
};
building.Add( dir );
RecursiveBuild( dir, directories [i], purchased );
}
}
} );
DirObj.Children = building.ToArray();
return DirObj;
}
string _FolderRoot = "/home/downloads/";
[Route( "api/product/showdownloads" )]
[HttpPost]
public async Task<IActionResult> ShowDownloads() {
try {
if( User.Identity != null && User.Identity.IsAuthenticated ) {
List<Claim> userClaims = User.Claims.ToList();
int UserID = -1;
foreach( Claim claim in userClaims ) {
if( claim.Type == "ID" ) {
UserID = Convert.ToInt32( claim.Value );
break;
}
}
List<ReceiptProduct> purchased = await _databaseService.GetAllReceiptsJoinedToProduct( new Account{ ID = UserID } );
byte[] datapacket = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(RecursiveBuild(new DirObj {
Path = @"\",
Type = FileType.Directory,
}, _FolderRoot, purchased)));
return new FileContentResult( datapacket, "text/html" );
}
return Unauthorized();
} catch {
return NotFound();
}
}
bool contains( string outer, string inner ) {
if ( outer.Length >= inner.Length ) {
for ( int i=0; i<outer.Length-inner.Length; i++ ) {
if ( outer.Substring(i, inner.Length) == inner ) {
return true;
}
}
}
return false;
}
[Route( "api/product/download" )]
[HttpGet]
public async Task<ActionResult> Download( [FromQuery] string Product ) {
try {
if( User.Identity != null && User.Identity.IsAuthenticated ) {
string? email = User.FindFirstValue(ClaimTypes.Email);
if( !string.IsNullOrEmpty( email ) ) {
Account? user = await _databaseService.GetAccount(email);
if (user != null){
List<Product>? games = await _databaseService.GetAllProducts();
foreach( Product product in games ) {
if ( contains( Product, product.URL ) ) {
Receipt? receipt = await _databaseService.GetReceipt(user, product);
if( receipt != null ) {
FileStream fileStream = new FileStream(_FolderRoot + Product, FileMode.Open, FileAccess.Read);
return new FileStreamResult( fileStream, "application/octet-stream" ) {
FileDownloadName = fileStream.Name
};
}
break;
}
}
}
}
return Unauthorized();
}
return Unauthorized();
} catch {
return NotFound();
}
}
[Route( "api/product/hotreload" )]
[HttpPost] // Not implimented in admin panel
public async Task UpdateStore() {
await HotReload( _databaseService );
}
public static async Task HotReload( DatabaseService ds ) {
CatalogItems = new List<Product>();
try {
CatalogItems = await ds.GetAllProducts();
} catch {
CatalogItems.Add( new Product() { ID = 0, Name = "offline prod1", Cost = 100, Description = "offline desc" } );
CatalogItems.Add( new Product() { ID = 1, Name = "offline prod2", Cost = 100, Description = "offline desc" } );
CatalogItems.Add( new Product() { ID = 2, Name = "offline prod3", Cost = 100, Description = "offline desc" } );
};
}
}
}
+40
View File
@@ -0,0 +1,40 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="9.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="9.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.WebApiCompatShim" Version="2.3.0" />
<PackageReference Include="MySql.Data" Version="9.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Stripe.net" Version="48.2.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MistoxWebsite.Client\MistoxWebsite.Client.csproj" />
<ProjectReference Include="..\MistoxWebsite.Shared\MistoxWebsite.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="wwwroot\css\bootstrap\bootstrap.min.css" />
<None Include="wwwroot\css\bootstrap\bootstrap.min.css.map" />
<None Include="wwwroot\css\open-iconic\FONT-LICENSE" />
<None Include="wwwroot\css\open-iconic\font\css\open-iconic-bootstrap.min.css" />
<None Include="wwwroot\css\open-iconic\font\fonts\open-iconic.eot" />
<None Include="wwwroot\css\open-iconic\font\fonts\open-iconic.otf" />
<None Include="wwwroot\css\open-iconic\font\fonts\open-iconic.svg" />
<None Include="wwwroot\css\open-iconic\font\fonts\open-iconic.ttf" />
<None Include="wwwroot\css\open-iconic\font\fonts\open-iconic.woff" />
<None Include="wwwroot\css\open-iconic\ICON-LICENSE" />
<None Include="wwwroot\css\open-iconic\README.md" />
</ItemGroup>
</Project>
+82
View File
@@ -0,0 +1,82 @@
using Microsoft.AspNetCore.Authentication.Cookies;
using MistoxWebsite.Server.Controllers;
using MistoxWebsite.Server.Services;
using MistoxWebsite.Server.Services.DatabaseService;
using Stripe;
var builder = WebApplication.CreateBuilder(args);
// Disable null warnings becuse string.IsNullOrEmpty checks for NULL or Empty
#pragma warning disable CS8600
#pragma warning disable CS8604
// Database Service
string? _dbserver = Environment.GetEnvironmentVariable("MySQLServer");
string dbserver = !string.IsNullOrEmpty(_dbserver) ? _dbserver : "localhost";
string? _dbuser = Environment.GetEnvironmentVariable("MySQLUser");
string dbUser = !string.IsNullOrEmpty(_dbuser) ? _dbuser : "root";
string? _dbdatabase = Environment.GetEnvironmentVariable("MySQLDatabase");
string dbdatabase = !string.IsNullOrEmpty(_dbdatabase) ? _dbdatabase : "mistox";
string? _dbpass = Environment.GetEnvironmentVariable("MySQLPass");
string dbPass = !string.IsNullOrEmpty(_dbpass) ? _dbpass : "";
string connStr = "server=" + dbserver + ";user=" + dbUser + ";database=" + dbdatabase + ";password=" + dbPass + ";port=3306;";
DatabaseService databaseService = new DatabaseService( connectionString: connStr );
await ProductController.HotReload( databaseService );
builder.Services.Add( new ServiceDescriptor( typeof( DatabaseService ), databaseService ) );
// Email Service
string? _eServer = Environment.GetEnvironmentVariable("EmailServer");
string EmailServer = !string.IsNullOrEmpty(_eServer) ? _eServer : "smtp.gmail.com";
string? _ePort = Environment.GetEnvironmentVariable("EmailPort");
int EmailPort = !string.IsNullOrEmpty(_ePort) ? Convert.ToInt32(_ePort) : 587;
string? _eAddress = Environment.GetEnvironmentVariable("EmailAddress");
string EmailAddress = !string.IsNullOrEmpty(_eAddress) ? _eAddress : "";
string? _ePassword = Environment.GetEnvironmentVariable("EmailPassword");
string EmailPassword = !string.IsNullOrEmpty(_ePassword) ? _ePassword : "";
EmailService Emailservice = new EmailService( EmailServer, EmailPort, EmailAddress, EmailPassword );
builder.Services.Add( new ServiceDescriptor( typeof( EmailService ), Emailservice ));
// Payment Service
string? StripeKey = Environment.GetEnvironmentVariable("StripeKey");
StripeConfiguration.ApiKey = StripeKey;
// Authentication Service
builder.Services.AddAuthentication( options => {
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
} ).AddCookie(options => {
options.Cookie.HttpOnly = true;
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Strict;
options.LoginPath = "/account/login";
options.LogoutPath = "/account/logout";
options.SlidingExpiration = true;
});
builder.Services.AddCors( o => o.AddDefaultPolicy( builder => {
builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); // No CORS
} ) );
// Pages Service
builder.Services.AddControllers();
builder.Services.AddRazorPages();
var app = builder.Build();
// Configure the HTTP request pipeline.
if( app.Environment.IsDevelopment() ) {
app.UseWebAssemblyDebugging();
} else {
app.UseHsts();
}
app.UseBlazorFrameworkFiles();
app.UseStaticFiles();
app.UseCors();
app.UseAuthentication();
app.MapControllers();
app.MapFallbackToFile("index.html");
app.Run();
+19
View File
@@ -0,0 +1,19 @@
{
"profiles": {
"IIS Express": {
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:6003",
"sslPort": 6003
},
"ProjectName": {
"commandName": "Project",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:6003",
"sslPort": 6003
}
}
}
@@ -0,0 +1,194 @@
using MistoxWebsite.Shared;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
namespace MistoxWebsite.Server.Services.DatabaseService {
public partial class DatabaseService {
public async Task<Account?> GetAccount( string UserNameOrEmail ) {
Account? account = null;
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
SELECT *
FROM Account
Left Join WebsiteData
On Account.ID = WebsiteData.AccountID
WHERE UserName = @UorE OR Email = @UorE;
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@UorE", UserNameOrEmail);
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
while( await reader.ReadAsync() ) {
if( reader == null ) {
break;
}
int _id = reader.GetInt32("ID");
string _username = reader.GetString("UserName");
string _email = reader.GetString("Email");
bool _emailVerified = reader.GetBoolean("EmailVerified");
string _passwordhash = reader.GetString("PasswordHash");
bool _failedpasswordlock = reader.GetBoolean( "FailedPasswordLock" );
int _passwordattempts = reader.GetInt32( "PasswordAttempts" );
int _curpasswordattempts = reader.GetInt32( "CurrentPasswordAttempts" );
string _role = reader.GetString( "Role" );
string _emailtoken = reader.GetString( "EmailToken" );
account = new Account() {
ID = _id,
UserName = _username,
Email = _email,
EmailVerified = _emailVerified,
PasswordHash = _passwordhash,
SiteData = new WebSiteData() {
AccountID = _id,
CurrentPasswordAttempts = _curpasswordattempts,
PasswordAttempts = _passwordattempts,
EmailToken = _emailtoken,
FailedPasswordLock = _failedpasswordlock,
Role = _role,
}
};
}
}
}
return account;
}
public async Task<Account?> GetAccountByID( int ID ) {
Account? account = null;
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
SELECT *
FROM Account
Left Join WebsiteData
On Account.ID = WebsiteData.AccountID
WHERE ID = @ID;
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@ID", ID);
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
while( await reader.ReadAsync() ) {
if( reader == null ) {
break;
}
int _id = reader.GetInt32("ID");
string _username = reader.GetString("UserName");
string _email = reader.GetString("Email");
bool _emailVerified = reader.GetBoolean("EmailVerified");
string _passwordhash = reader.GetString("PasswordHash");
bool _failedpasswordlock = reader.GetBoolean( "FailedPasswordLock" );
int _passwordattempts = reader.GetInt32( "PasswordAttempts" );
int _curpasswordattempts = reader.GetInt32( "CurrentPasswordAttempts" );
string _role = reader.GetString( "Role" );
string _emailtoken = reader.GetString( "EmailToken" );
account = new Account() {
ID = _id,
UserName = _username,
Email = _email,
EmailVerified = _emailVerified,
PasswordHash = _passwordhash,
SiteData = new WebSiteData() {
AccountID = _id,
CurrentPasswordAttempts = _passwordattempts,
PasswordAttempts = _passwordattempts,
EmailToken = _emailtoken,
FailedPasswordLock = _failedpasswordlock,
Role = _role,
}
};
}
}
}
return account;
}
public async Task SetAccount( Account Update ) {
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
UPDATE Account SET
UserName = @UserName,
Email = @Email,
EmailVerified = @EmailVerified,
PasswordHash = @PasswordHash
WHERE ID = @ID;
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@UserName", Update.UserName);
cmd.Parameters.AddWithValue("@Email", Update.Email);
cmd.Parameters.AddWithValue("@EmailVerified", Update.EmailVerified);
cmd.Parameters.AddWithValue("@PasswordHash", Update.PasswordHash);
cmd.Parameters.AddWithValue("@ID", Update.ID);
await cmd.ExecuteNonQueryAsync();
await UpdateWebsiteData( Update, Update.SiteData );
}
}
public async Task NewAccount( Account Profile ) {
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
int EmailVer = Profile.EmailVerified ? 1 : 0;
string command = @"
INSERT INTO Account
(UserName,Email,EmailVerified,PasswordHash)
VALUES
(@UserName,@Email,@EmailVerified,@PasswordHash);
SELECT ID FROM Account
WHERE UserName = @UserName;
";
MySqlCommand cmd = new MySqlCommand( command , connection);
cmd.Parameters.AddWithValue("@UserName", Profile.UserName);
cmd.Parameters.AddWithValue("@Email", Profile.Email);
cmd.Parameters.AddWithValue("@EmailVerified", Profile.EmailVerified);
cmd.Parameters.AddWithValue("@PasswordHash", Profile.PasswordHash);
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
while( await reader.ReadAsync() ) {
if( reader == null ) {
break;
}
int _id = reader.GetInt32("ID");
Profile.ID = _id;
}
}
await NewWebsiteData( Profile, Profile.SiteData );
}
}
public async Task DeleteAccount( Account Profile ) {
using( MySqlConnection connection = GetConnection() ) {
MySqlCommand cmd;
connection.Open();
string command = @"
DELETE FROM Account WHERE ID = @ID;
DELETE FROM AccountInventory WHERE AccountID = @ID;
DELETE FROM ProjectMistData WHERE AccountID = @ID;
DELETE FROM Cart WHERE AccountID = @ID;
DELETE FROM WebsiteData WHERE AccountID = @ID;
";
cmd = new MySqlCommand( command, connection );
cmd.Parameters.AddWithValue("@ID", Profile.ID);
await cmd.ExecuteNonQueryAsync();
}
}
}
}
@@ -0,0 +1,116 @@
using MistoxWebsite.Shared;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
// Account inventory needs to know whether there is already an object with the specified PK before making a new item
// If item exists already update the one that already exists
namespace MistoxWebsite.Server.Services.DatabaseService {
public partial class DatabaseService {
public async Task<List<UserInventory>> GetInventory( Account account, Product product ) {
List<UserInventory> list = new List<UserInventory>();
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
SELECT * FROM AccountInventory
WHERE AccountID = @AccountID AND ProductID = @ProductID;
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@AccountID", account.ID);
cmd.Parameters.AddWithValue("@ProductID", product.ID);
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
while( await reader.ReadAsync() ) {
if( reader == null ) {
break;
}
string _item = reader.GetString("Item");
int _quantity = reader.GetInt32("Quantity");
string _stats = reader.GetString("Stats");
list.Add( new UserInventory() {
Item = _item,
Quantity = _quantity,
Stats = _stats
} );
}
}
}
return list;
}
async Task UpdateInventory( MySqlConnection connection, AccountInventory item ) {
string command = @"
UPDATE AccountInventory
SET AccountID = @AccountID,
ProductID = @ProductID,
Item = @Item,
Quantity = @Quantity,
Stats = @Stats
WHERE (AccountID = @AccountID AND ProductID = @ProductID AND Item = @Item);
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@AccountID", item.AccountID);
cmd.Parameters.AddWithValue("@ProductID", item.ProductID);
cmd.Parameters.AddWithValue("@Item", item.Item);
cmd.Parameters.AddWithValue("@Quantity", item.Quantity);
cmd.Parameters.AddWithValue("@Stats", item.Stats);
await cmd.ExecuteNonQueryAsync();
}
async Task NewInventory( MySqlConnection connection, AccountInventory item ) {
string command = @"
INSERT INTO AccountInventory (AccountID, ProductID, Item, Quantity, Stats)
VALUES
(@AccountID, @ProductID, @Item, @Quantity, @Stats);
";
MySqlCommand cmd = new MySqlCommand( command , connection);
cmd.Parameters.AddWithValue("@AccountID", item.AccountID);
cmd.Parameters.AddWithValue("@ProductID", item.ProductID);
cmd.Parameters.AddWithValue("@Item", item.Item);
cmd.Parameters.AddWithValue("@Quantity", item.Quantity);
cmd.Parameters.AddWithValue("@Stats", item.Stats);
await cmd.ExecuteNonQueryAsync();
}
// Test to see if reader read does what its supposed to
// Not fully implimented
public async Task SetInventory( Account account, Product game, List<UserInventory> Item ) {
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
foreach( UserInventory item in Item ) {
bool exists = false;
MySqlCommand cmd = new MySqlCommand("SELECT * FROM AccountInventory WHERE AccountID = '" + account.ID + "' AND ProductID = '" + game.ID + "' AND Item = '" + item.Item.ToLower() + "'", connection);
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
exists = reader.HasRows;
}
if( exists ) {
await UpdateInventory( connection, new AccountInventory() {
AccountID = account.ID,
ProductID = game.ID,
Item = item.Item,
Quantity = item.Quantity,
Stats = item.Stats
} );
} else {
await NewInventory( connection, new AccountInventory() {
AccountID = account.ID,
ProductID = game.ID,
Item = item.Item,
Quantity = item.Quantity,
Stats = item.Stats
} );
}
}
}
}
}
}
+82
View File
@@ -0,0 +1,82 @@
using MistoxWebsite.Shared;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
namespace MistoxWebsite.Server.Services.DatabaseService {
public partial class DatabaseService {
public async Task<List<Cart>> GetCart( Account account ) {
List<Cart> list = new List<Cart>();
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
SELECT * FROM Cart
WHERE AccountID = @AccountID;
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@AccountID", account.ID);
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
while( await reader.ReadAsync() ) {
if( reader == null ) {
break;
}
int _id = reader.GetInt32("ID");
int _accountid = reader.GetInt32("AccountID");
int _productid = reader.GetInt32("ProductID");
list.Add( new Cart() {
ID = _id,
AccountID = _accountid,
ProductID = _productid
} );
}
}
}
return list;
}
public async Task AddToCart( Cart item ) {
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
INSERT INTO Cart
(AccountID, ProductID)
VALUES
(@AccountID, @ProductID);
";
MySqlCommand cmd = new MySqlCommand( command , connection);
cmd.Parameters.AddWithValue("@AccountID", item.AccountID);
cmd.Parameters.AddWithValue("@ProductID", item.ProductID);
await cmd.ExecuteNonQueryAsync();
}
}
public async Task RemoveFromCart( Cart item ) {
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = "DELETE FROM Cart WHERE AccountID=" + item.AccountID + " AND ProductID=" + item.ProductID + ";";
MySqlCommand cmd = new MySqlCommand( command , connection);
await cmd.ExecuteNonQueryAsync();
}
}
public async Task ClearCart( Account account ) {
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
DELETE FROM Cart
WHERE AccountID = @AccountID;
";
MySqlCommand cmd = new MySqlCommand( command , connection);
cmd.Parameters.AddWithValue("@AccountID", account.ID);
await cmd.ExecuteNonQueryAsync();
}
}
}
}
@@ -0,0 +1,15 @@
using MySql.Data.MySqlClient;
namespace MistoxWebsite.Server.Services.DatabaseService {
public partial class DatabaseService {
public string ConnectionString {
get; set;
}
public DatabaseService( string connectionString ) {
ConnectionString = connectionString;
}
MySqlConnection GetConnection() {
return new MySqlConnection( ConnectionString );
}
}
}
@@ -0,0 +1,122 @@
using MistoxWebsite.Shared;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
namespace MistoxWebsite.Server.Services.DatabaseService {
public partial class DatabaseService {
public async Task<PageLoadObject> getPageLoadObject( int AccountID ) {
PageLoadObject account = new PageLoadObject();
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
SELECT * FROM Account
INNER JOIN WebsiteData
ON Account.ID = WebsiteData.AccountID
WHERE ID = @AccountID
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@AccountID", AccountID);
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
while( await reader.ReadAsync() ) {
if( reader == null ) {
break;
}
int _id = reader.GetInt32(0);
string _username = reader.GetString(1);
string _email = reader.GetString(2);
bool _emailVerified = reader.GetBoolean(3);
string _passwordhash = reader.GetString(4);
bool _failedPasswordLock = reader.GetBoolean(6);
int _passwordAttempts = reader.GetInt32(7);
int _currentPasswordAttempts = reader.GetInt32(8);
string _role = reader.GetString(9);
string _emailToken = reader.GetString(10);
account.claims = new AccountClaims() {
Email = _email,
EmailVerified = _emailVerified.ToString(),
FailedPasswordLock = _failedPasswordLock.ToString(),
Role = _role,
UserName = _username,
};
account.user = new Account() {
ID = _id,
UserName = _username,
Email = _email,
EmailVerified = _emailVerified,
PasswordHash = _passwordhash,
SiteData = new WebSiteData() {
AccountID = _id,
CurrentPasswordAttempts = _currentPasswordAttempts,
PasswordAttempts = _passwordAttempts,
EmailToken = _emailToken,
FailedPasswordLock = _failedPasswordLock,
Role = _role,
}
};
}
}
account.products = new List<Product>();
account.receipts = new List<Receipt>();
command = @"
SELECT * FROM Product
LEFT JOIN Receipt
ON ID = Receipt.ProductID
WHERE AccountID is Null or AccountID = @AccountID;
";
MySqlCommand cmd2 = new MySqlCommand(command, connection);
cmd2.Parameters.AddWithValue("@AccountID", AccountID);
using( DbDataReader reader = await cmd2.ExecuteReaderAsync() ) {
while( await reader.ReadAsync() ) {
if( reader == null ) {
break;
}
int _productID = !await reader.IsDBNullAsync(0) ? reader.GetInt32(0) : -1;
string _gameName = !await reader.IsDBNullAsync(1) ? reader.GetString(1) : "";
string _gameDesc = !await reader.IsDBNullAsync(2) ? reader.GetString(2) : "";
string _gameImg = !await reader.IsDBNullAsync(3) ? reader.GetString(3) : "";
int _gameCost = !await reader.IsDBNullAsync(4) ? reader.GetInt32(4) : 37707;
string _gameURL = !await reader.IsDBNullAsync(5) ? reader.IsDBNull(5) ? "" : reader.GetString(5) : "Something not common";
int _receiptAccountID = !await reader.IsDBNullAsync(6) ? reader.IsDBNull(6) ? -1 : reader.GetInt32(6) : -1;
string _receiptID = !await reader.IsDBNullAsync(8) ? reader.IsDBNull(8) ? "" : reader.GetString(8) : "";
DateTime _receiptTime = !await reader.IsDBNullAsync(10) ? reader.GetDateTime(10) : DateTime.Now;
string[] _imageList = _gameImg.Split('|', StringSplitOptions.RemoveEmptyEntries);
account.products.Add( new Product {
ID = _productID,
Cost = _gameCost,
Description = _gameDesc,
Name = _gameName,
URL = _gameURL,
Images = _imageList.ToList()
} );
if( _receiptAccountID != -1 ) {
account.receipts.Add( new Receipt {
AccountID = _receiptAccountID,
ProductID = _productID,
ReceiptID = _receiptID,
Time = _receiptTime
} );
}
}
}
}
return account;
}
}
}
@@ -0,0 +1,140 @@
using MistoxWebsite.Shared;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
namespace MistoxWebsite.Server.Services.DatabaseService {
public partial class DatabaseService {
public async Task<Product?> GetProduct( int ID ) {
Product? items = null;
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
SELECT * FROM Product
WHERE ID = @ID;
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@ID", ID);
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
while( await reader.ReadAsync() ) {
if( reader == null ) {
break;
}
int _id = reader.GetInt32("ID");
string _name = reader.GetString("Name");
string _description = reader.GetString("Description");
string _images = reader.GetString("Images");
int _cost = reader.GetInt32("Cost");
string _url = reader.GetString("URL");
string[] _imageList = _images.Split('|', StringSplitOptions.RemoveEmptyEntries);
items = new Product() {
ID = _id,
Name = _name,
Description = _description,
Cost = _cost,
Images = _imageList.ToList(),
URL = _url
};
}
}
}
return items;
}
public async Task<List<Product>> GetAllProducts() {
List<Product> items = new List<Product>();
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
MySqlCommand cmd = new MySqlCommand("SELECT * FROM Product", connection);
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
while( await reader.ReadAsync() ) {
if( reader == null ) {
break;
}
int _id = reader.GetInt32("ID");
string _name = reader.GetString("Name");
string _description = reader.GetString("Description");
string _images = reader.GetString("Images");
int _cost = reader.GetInt32("Cost");
string _url = reader.GetString("URL");
string[] _imageList = _images.Split('|', StringSplitOptions.RemoveEmptyEntries);
items.Add( new Product() {
ID = _id,
Name = _name,
Description = _description,
Cost = _cost,
Images = _imageList.ToList(),
URL = _url
} );
}
}
}
return items;
}
public async Task NewProduct( Product Item ) {
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string buildingImages = "";
foreach( string cur in Item.Images ) {
buildingImages = buildingImages + "|" + cur;
}
string command = @"
INSERT INTO Product
(Name, Description, Images, Cost, URL)
VALUES
(@Name, @Description, @Images, @Cost, @URL);
";
MySqlCommand cmd = new MySqlCommand( command , connection);
cmd.Parameters.AddWithValue("@Name", Item.Name);
cmd.Parameters.AddWithValue("@Description", Item.Description);
cmd.Parameters.AddWithValue("@Images", buildingImages);
cmd.Parameters.AddWithValue("@Cost", Item.Cost);
cmd.Parameters.AddWithValue("@URL", Item.URL);
await cmd.ExecuteNonQueryAsync();
}
}
public async Task UpdateProduct( Product Item ) {
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string buildingImages = "";
foreach( string cur in Item.Images ) {
buildingImages = buildingImages + "|" + cur;
}
string command = @"UPDATE Product SET
Name = @Name,
Description = @Description,
Images = @Images,
Cost = @Cost,
URL = @URL
WHERE ID = @ID;
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@Name", Item.Name);
cmd.Parameters.AddWithValue("@Description", Item.Description);
cmd.Parameters.AddWithValue("@Images", Item.Images);
cmd.Parameters.AddWithValue("@Cost", Item.Cost);
cmd.Parameters.AddWithValue("@URL", Item.URL);
cmd.Parameters.AddWithValue("@ID", Item.ID);
await cmd.ExecuteNonQueryAsync();
}
}
}
}
@@ -0,0 +1,71 @@
using MistoxWebsite.Shared;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
namespace MistoxWebsite.Server.Services.DatabaseService {
public partial class DatabaseService {
public async Task<ProjectMistData?> GetProjectMistData( int ID ) {
ProjectMistData? items = null;
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
SELECT * FROM ProjectMistData
WHERE AccountID = @AccountID;
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@AccountID", ID);
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
while( await reader.ReadAsync() ) {
if( reader == null ) {
break;
}
int _id = reader.GetInt32("AccountID");
items = new ProjectMistData() {
AccountID = _id,
};
}
}
}
return items;
}
public async Task NewProjectMistData( ProjectMistData data ) {
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
INSERT INTO ProjectMistData
(AccountID)
VALUES
(@AccountID);
";
MySqlCommand cmd = new MySqlCommand( command , connection);
cmd.Parameters.AddWithValue("@AccountID", data.AccountID);
await cmd.ExecuteNonQueryAsync();
}
}
public async Task UpdateProjectMistData( ProjectMistData data ) {
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
UPDATE ProjectMistData SET
AccountID = @AccountID
WHERE AccountID = @AccountID;
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@AccountID", data.AccountID);
await cmd.ExecuteReaderAsync();
}
}
}
}
@@ -0,0 +1,170 @@
using MistoxWebsite.Shared;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
namespace MistoxWebsite.Server.Services.DatabaseService {
public partial class DatabaseService {
public async Task<List<Receipt>> GetAllReceipts( Account account ) {
List<Receipt> receipts = new List<Receipt> ();
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
SELECT * FROM Receipt
WHERE AccountID = @AccountID;
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@AccountID", account.ID);
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
while( await reader.ReadAsync() ) {
if( reader == null ) {
break;
}
int _accountid = reader.GetInt32("AccountID");
int _gameid = reader.GetInt32("ProductID");
string _receiptid = reader.GetString("ReceiptID");
int _lineitem = reader.GetInt32("LineItem");
DateTime _receiptdate = reader.GetDateTime("Time");
int _taxamount = reader.GetInt32("TaxAmount");
int _totalcost = reader.GetInt32("TotalCost");
receipts.Add( new Receipt() {
AccountID = _accountid,
ProductID = _gameid,
ReceiptID = _receiptid,
Time = _receiptdate,
TotalCost = _totalcost,
TaxAmount = _taxamount,
LineItem = _lineitem
} );
}
}
}
return receipts;
}
public async Task<List<ReceiptProduct>> GetAllReceiptsJoinedToProduct( Account account ) {
List<ReceiptProduct> join = new List<ReceiptProduct> ();
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
SELECT * FROM Receipt
LEFT JOIN Product
ON Receipt.ProductID = Product.ID
WHERE AccountID = @AccountID
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@AccountID", account.ID);
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
while( await reader.ReadAsync() ) {
if( reader == null ) {
break;
}
int _accountid = !reader.IsDBNull( "AccountID" ) ? reader.GetInt32("AccountID") : -1;
int _gameid = !reader.IsDBNull( "ProductID" ) ? reader.GetInt32("ProductID") : 0;
string _receiptid = !reader.IsDBNull( "ReceiptID" ) ? reader.GetString("ReceiptID") : "";
int _lineitem = !reader.IsDBNull( "LineItem" ) ? reader.GetInt32("LineItem") : 0;
DateTime _receiptdate = !reader.IsDBNull( "Time" ) ? reader.GetDateTime("Time") : DateTime.Now;
int _taxamount = !reader.IsDBNull( "TaxAmount" ) ? reader.GetInt32("TaxAmount") : 0;
int _totalcost = !reader.IsDBNull( "TotalCost" ) ? reader.GetInt32("TotalCost") : 0;
int _id = !reader.IsDBNull( "ID" ) ? reader.GetInt32("ID") : 0;
string _name = !reader.IsDBNull( "Name" ) ? reader.GetString("Name") : "";
string _desc = !reader.IsDBNull( "Description" ) ? reader.GetString("Description") : "";
int _cost = !reader.IsDBNull( "Cost" ) ? reader.GetInt32("Cost") : 0;
string _url = !reader.IsDBNull( "URL" ) ? reader.GetString("URL") : "Something Random That Wont Ever Be In A URL";
join.Add( new ReceiptProduct() {
receipt = new Receipt {
AccountID = _accountid,
ProductID = _gameid,
ReceiptID = _receiptid,
Time = _receiptdate,
TotalCost = _totalcost,
TaxAmount = _taxamount,
LineItem = _lineitem
},
product = new Product() {
ID = _id,
Cost = _cost,
Description = _desc,
Name = _name,
URL = _url
}
} );
}
}
}
return join;
}
public async Task<Receipt?> GetReceipt( Account account, Product game ) {
Receipt? receipt = null;
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
SELECT * FROMReceipt
WHERE AccountID = @AccountID AND ProductID = @ProductID;
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@AccountID", account.ID);
cmd.Parameters.AddWithValue("@ProductID", game.ID);
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
while( await reader.ReadAsync() ) {
if( reader == null ) {
break;
}
int _accountid = reader.GetInt32("AccountID");
int _gameid = reader.GetInt32("ProductID");
string _receiptid = reader.GetString("ReceiptID");
int _lineitem = reader.GetInt32("LineItem");
DateTime _receiptdate = reader.GetDateTime("Time");
int _taxamount = reader.GetInt32("TaxAmount");
int _totalcost = reader.GetInt32("TotalCost");
receipt = new Receipt() {
AccountID = _accountid,
ProductID = _gameid,
ReceiptID = _receiptid,
Time = _receiptdate,
TotalCost = _totalcost,
TaxAmount = _taxamount,
LineItem = _lineitem
};
}
}
}
return receipt;
}
public async Task NewReceipt( Receipt receipt ) {
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
INSERT INTO Receipt
(AccountID, ProductID, ReceiptID, LineItem, TaxAmount, TotalCost, Time)
VALUES
(@AccountID, @ProductID, @ReceiptID, @LineItem, @TaxAmount, @TotalCost, @Time)
";
MySqlCommand cmd = new MySqlCommand( command , connection);
cmd.Parameters.AddWithValue("@AccountID", receipt.AccountID);
cmd.Parameters.AddWithValue("@ProductID", receipt.ProductID);
cmd.Parameters.AddWithValue("@ReceiptID", receipt.ReceiptID);
cmd.Parameters.AddWithValue("@LineItem", receipt.LineItem);
cmd.Parameters.AddWithValue("@TaxAmount", receipt.TaxAmount);
cmd.Parameters.AddWithValue("@TotalCost", receipt.TotalCost);
cmd.Parameters.AddWithValue("@Time", receipt.Time); // Just incase i need this in the future | receipt.Time.ToString( "yyyy-MM-dd hh:mm:ss" )
await cmd.ExecuteNonQueryAsync();
}
}
}
}
@@ -0,0 +1,115 @@
using MistoxWebsite.Shared;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
namespace MistoxWebsite.Server.Services.DatabaseService {
public partial class DatabaseService {
public async Task<WebSiteData?> GetWebsiteData( Account account ) {
WebSiteData? webSiteData = null;
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
SELECT * FROM WebsiteData
WHERE AccountID = @AccountID;
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@AccountID", account.ID);
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
while( await reader.ReadAsync() ) {
if( reader == null ) {
break;
}
int _id = 0;
bool _failedpasswordlock = false;
int _passwordattempts = 5;
int _curpasswordattempts = 0;
string _role = "";
string _emailtoken = "";
if( !reader.IsDBNull( "AccountID" ) ) {
_id = reader.GetInt32( "AccountID" );
}
if( !reader.IsDBNull( "FailedPasswordLock" ) ) {
_failedpasswordlock = reader.GetBoolean( "FailedPasswordLock" );
}
if( !reader.IsDBNull( "PasswordAttempts" ) ) {
_passwordattempts = reader.GetInt32( "PasswordAttempts" );
}
if( !reader.IsDBNull( "CurrentPasswordAttempts" ) ) {
_curpasswordattempts = reader.GetInt32( "CurrentPasswordAttempts" );
}
if( !reader.IsDBNull( "Role" ) ) {
_role = reader.GetString( "Role" );
}
if( !reader.IsDBNull( "EmailToken" ) ) {
_emailtoken = reader.GetString( "EmailToken" );
}
webSiteData = new WebSiteData() {
AccountID = _id,
FailedPasswordLock = _failedpasswordlock,
CurrentPasswordAttempts = _curpasswordattempts,
PasswordAttempts = _passwordattempts,
EmailToken = _emailtoken,
Role = _role,
};
}
}
}
return webSiteData;
}
public async Task NewWebsiteData( Account account, WebSiteData data ) {
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
INSERT INTO WebsiteData
(AccountID, FailedPasswordLock, PasswordAttempts, CurrentPasswordAttempts, Role, EmailToken)
VALUES
(@AccountID, @FailedPasswordLock, @PasswordAttempts, @CurrentPasswordAttempts, @Role, @EmailToken);
";
MySqlCommand cmd = new MySqlCommand( command , connection);
cmd.Parameters.AddWithValue("@AccountID", account.ID);
cmd.Parameters.AddWithValue("@FailedPasswordLock", data.FailedPasswordLock);
cmd.Parameters.AddWithValue("@PasswordAttempts", data.PasswordAttempts);
cmd.Parameters.AddWithValue("@CurrentPasswordAttempts", data.CurrentPasswordAttempts);
cmd.Parameters.AddWithValue("@Role", data.Role);
cmd.Parameters.AddWithValue("@EmailToken", data.EmailToken);
await cmd.ExecuteNonQueryAsync();
}
}
public async Task UpdateWebsiteData( Account account, WebSiteData data ) {
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
UPDATE WebsiteData SET
FailedPasswordLock = @FailedPasswordLock,
PasswordAttempts = @PasswordAttempts,
CurrentPasswordAttempts = @CurrentPasswordAttempts,
Role = @Role,
EmailToken = @EmailToken
WHERE AccountID = @AccountID;
";
MySqlCommand cmd = new MySqlCommand(command, connection);
cmd.Parameters.AddWithValue("@AccountID", account.ID);
cmd.Parameters.AddWithValue("@FailedPasswordLock", data.FailedPasswordLock);
cmd.Parameters.AddWithValue("@PasswordAttempts", data.PasswordAttempts);
cmd.Parameters.AddWithValue("@CurrentPasswordAttempts", data.CurrentPasswordAttempts);
cmd.Parameters.AddWithValue("@Role", data.Role);
cmd.Parameters.AddWithValue("@EmailToken", data.EmailToken);
await cmd.ExecuteNonQueryAsync();
}
}
}
}
@@ -0,0 +1,41 @@
using System.Net.Mail;
namespace MistoxWebsite.Server.Services {
public partial class EmailService {
public Dictionary<string, DateTime> _SentEmails = new Dictionary<string, DateTime>();
public string EmailServer = "";
public string EmailAddress = "";
public string EmailPassword = "";
public int EmailPort;
public EmailService( string _EmailServer, int _EmailPort, string _EmailAddress, string _EmailPassword ) {
EmailServer = _EmailServer;
EmailPort = _EmailPort;
EmailAddress = _EmailAddress;
EmailPassword = _EmailPassword;
}
public string Send( string Destination, string Subject, string Body ) {
using (SmtpClient client = new SmtpClient( EmailServer, EmailPort )){
client.EnableSsl = true;
client.Credentials = new System.Net.NetworkCredential( EmailAddress, EmailPassword );
try {
MailMessage msg = new MailMessage(){
IsBodyHtml = true,
Subject = Subject,
Body = Body
};
msg.From = new MailAddress( EmailAddress, "no-reply" );
msg.To.Add( new MailAddress( Destination ) );
client.Send( msg );
return "Success";
} catch( Exception e ) {
return "An Error Has Occurred Sending Email : " + e.ToString();
}
}
}
}
}
@@ -0,0 +1,53 @@
using System.Net.Mail;
namespace MistoxWebsite.Server.Services {
public partial class EmailService {
// @UserName
// @ResetPassWord
// https://mistox.com/account/resetpassword?UserName=@UserName&ResetPwd=@ResetPassWord
public static string ResetPasswordSubject = "Password Reset Request";
public static string ResetPasswordEmail = @"
<!DOCTYPE html>
<html lang=""en"">
<head>
<meta charset=""UTF-8"">
<meta name=""viewport"" content=""width=device-width, initial-scale=1.0"">
<title>Password Reset</title>
</head>
<body style=""font-family: Arial, sans-serif; background-color: #f4f4f4; margin: 0; padding: 0;"">
<table role=""presentation"" style=""width: 100%; background-color: #f4f4f4; padding: 20px 0;"">
<tr>
<td>
<table role=""presentation"" style=""max-width: 600px; width: 100%; background-color: #ffffff; margin: 0 auto; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);"">
<tr>
<td style=""padding: 20px; text-align: center; background-color: #4CAF50; color: #ffffff; border-top-left-radius: 8px; border-top-right-radius: 8px;"">
<h2>Password Reset Request</h2>
</td>
</tr>
<tr>
<td style=""padding: 20px; text-align: left; font-size: 16px; color: #333333;"">
<p>Hi @UserName,</p>
<p>We received a request to reset your password. You can reset your password by clicking the button below:</p>
<p style=""text-align: center;"">
<a href=""https://mistox.com/account/resetpassword?UserName=@UserName&ResetPwd=@ResetPassWord"" style=""background-color: #4CAF50; color: #ffffff; text-decoration: none; padding: 15px 25px; font-size: 16px; border-radius: 5px; display: inline-block;"">Reset Password</a>
</p>
<p>If you didn't request a password reset, you can safely ignore this email.</p>
<p>Best regards</p>
</td>
</tr>
<tr>
<td style=""padding: 10px; text-align: center; background-color: #f4f4f4; color: #888888; font-size: 12px; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;"">
<p>If you have any questions, feel free to <a href=""mailto:webmaster@mistox.com"" style=""color: #4CAF50; text-decoration: none;"">contact support</a>.</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
";
}
}
@@ -0,0 +1,54 @@
using System.Net.Mail;
namespace MistoxWebsite.Server.Services {
public partial class EmailService {
// @UserName
// @VerifyPassword
// https://mistox.com/api/account/verifyemail?UserName=@UserName&Guid=@VerifyPassword
public static string VerifyEmailSubject = "Verify Your Email Address";
public static string VerifyEmailEmail = @"
<!DOCTYPE html>
<html lang=""en"">
<head>
<meta charset=""UTF-8"">
<meta name=""viewport"" content=""width=device-width, initial-scale=1.0"">
<title>Verify Your Email</title>
</head>
<body style=""font-family: Arial, sans-serif; background-color: #f4f4f4; margin: 0; padding: 0;"">
<table role=""presentation"" style=""width: 100%; background-color: #f4f4f4; padding: 20px 0;"">
<tr>
<td>
<table role=""presentation"" style=""max-width: 600px; width: 100%; background-color: #ffffff; margin: 0 auto; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);"">
<tr>
<td style=""padding: 20px; text-align: center; background-color: #4CAF50; color: #ffffff; border-top-left-radius: 8px; border-top-right-radius: 8px;"">
<h2>Verify Email Request</h2>
</td>
</tr>
<tr>
<td style=""padding: 20px; text-align: left; font-size: 16px; color: #333333;"">
<p>Hi @UserName,</p>
<p>Thank you for making an account with us:</p>
<p>In order to start using your account we need to verify your email address by clicking the link below:</p>
<p style=""text-align: center;"">
<a href=""https://mistox.com/account/verifyemail?UserName=@UserName&Guid=@VerifyPassword"" style=""background-color: #4CAF50; color: #ffffff; text-decoration: none; padding: 15px 25px; font-size: 16px; border-radius: 5px; display: inline-block;"">Verify Email</a>
</p>
<p>If you didn't create an account please ignore this email.</p>
<p>Best regards</p>
</td>
</tr>
<tr>
<td style=""padding: 10px; text-align: center; background-color: #f4f4f4; color: #888888; font-size: 12px; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;"">
<p>If you have any questions, feel free to <a href=""mailto:webmaster@mistox.com"" style=""color: #4CAF50; text-decoration: none;"">contact support</a>.</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
";
}
}
+179
View File
@@ -0,0 +1,179 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Stripe-Payments</title>
<script src="https://js.stripe.com/v3/"></script>
<style>
#submit {
width: 200px;
height: 40px;
margin-left: calc(50% - 100px);
margin-top: 30px;
color: #fff;
background-color: #393;
font-size: 16px;
text-decoration: none;
text-transform: uppercase;
overflow: hidden;
transition: .5s;
letter-spacing: 4px;
border: 1px solid #8F7CEC;
}
#submit:hover {
background: #353;
color: #fff;
border-radius: 5px;
border-color: #353;
}
</style>
</head>
<body>
<form id="payment-form">
<div id="link-authentication-element">
<!--Stripe.js injects the Link Authentication Element-->
</div>
<div id="payment-element">
<!--Stripe.js injects the Payment Element-->
</div>
<button id="submit">
<div class="spinner hidden" id="spinner"></div>
<span id="button-text">Pay now</span>
</button>
<div id="payment-message" class="hidden"></div>
</form>
<script>
// This is your test publishable API key.
const stripe = Stripe('pk_live_51LBODxCozZzTNCNhFdVbzm93F1N3Kk5sEiOyUYeU8GlqxF8AkS6h1JOkIqmFJ1hBmkBCEEa8cfBCY7RotHlweS7g00UzyxkUnO');
let elements;
initialize();
checkStatus();
document.querySelector("#payment-form").addEventListener("submit", handleSubmit);
let emailAddress = '';
// Fetches a payment intent and captures the client secret
async function initialize() {
const response = await fetch("/api/getCheckoutToken?userID=" + new URL(window.location.href).searchParams.get("userID"), {
method: "POST",
headers: { "Content-Type": "text/plain" },
body: ""
});
const clientSecret = await response.text();
const appearance = {
theme: 'night',
};
elements = stripe.elements({ appearance, clientSecret });
const linkAuthenticationElement = elements.create("linkAuthentication");
linkAuthenticationElement.mount("#link-authentication-element");
linkAuthenticationElement.on('change', (event) => {
emailAddress = event.value.email;
});
const paymentElementOptions = {
layout: "tabs",
};
const paymentElement = elements.create("payment", paymentElementOptions);
paymentElement.mount("#payment-element");
}
async function handleSubmit(e) {
e.preventDefault();
setLoading(true);
const { error } = await stripe.confirmPayment({
elements,
confirmParams: {
// Make sure to change this to your payment completion page
return_url: "https://mistox.net/store/payment/success",
receipt_email: emailAddress,
},
});
// This point will only be reached if there is an immediate error when
// confirming the payment. Otherwise, your customer will be redirected to
// your `return_url`. For some payment methods like iDEAL, your customer will
// be redirected to an intermediate site first to authorize the payment, then
// redirected to the `return_url`.
if (error.type === "card_error" || error.type === "validation_error") {
showMessage(error.message);
} else {
showMessage("An unexpected error occurred.");
}
setLoading(false);
}
// Fetches the payment intent status after payment submission
async function checkStatus() {
const clientSecret = new URLSearchParams(window.location.search).get(
"payment_intent_client_secret"
);
if (!clientSecret) {
return;
}
const { paymentIntent } = await stripe.retrievePaymentIntent(clientSecret);
switch (paymentIntent.status) {
case "succeeded":
showMessage("Payment succeeded!");
break;
case "processing":
showMessage("Your payment is processing.");
break;
case "requires_payment_method":
showMessage("Your payment was not successful, please try again.");
break;
default:
showMessage("Something went wrong.");
break;
}
}
// ------- UI helpers -------
function showMessage(messageText) {
const messageContainer = document.querySelector("#payment-message");
messageContainer.classList.remove("hidden");
messageContainer.textContent = messageText;
setTimeout(function () {
messageContainer.classList.add("hidden");
messageText.textContent = "";
}, 4000);
}
// Show a spinner on payment submission
function setLoading(isLoading) {
if (isLoading) {
// Disable the button and show a spinner
document.querySelector("#submit").disabled = true;
document.querySelector("#spinner").classList.remove("hidden");
document.querySelector("#button-text").classList.add("hidden");
} else {
document.querySelector("#submit").disabled = false;
document.querySelector("#spinner").classList.add("hidden");
document.querySelector("#button-text").classList.remove("hidden");
}
}
</script>
</body>
</html>
+192
View File
@@ -0,0 +1,192 @@
<html>
<head>
<title>HTML_Snake</title>
</head>
<body onkeydown='return keyDown(event)'; style="background-color: #333;">
<h1 id="Score" style="width: 100%; text-align: center; color:#fff;">Score : 0</h1>
<div id="BODY" style="position: relative; margin-bottom: 5px; margin-left: 50%; right: 300px; background-color: #666; width: 600px; height: 600px;">
<script>
var snake = [];
var score = 0;
var posX = 12;
var posY = 15;
var colX, colY;
var saves = "";
var paused = false;
var direction = 2;
var wasCollected = false;
var body = document.getElementById("BODY");
function set(name,value) {
var expires = "";
var date = new Date();
date.setTime(date.getTime() + (9999*24*60*60*1000));
expires = "; expires=" + date.toUTCString();
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
function get(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
function hsl2rgb(h,s,l) {
let a=s*Math.min(l,1-l);
let f= (n,k=(n+h/30)%12) => l - a*Math.max(Math.min(k-3,9-k,1),-1);
return [f(0),f(8),f(4)];
}
var degree = 0;
function newTail(x, y){
degree += 5;
if(degree > 359){
degree = 0;
}
var color = hsl2rgb(degree, .6, .5);
var r = Math.floor(color[0] * 255).toString(16);
var g = Math.floor(color[1] * 255).toString(16);
var b = Math.floor(color[2] * 255).toString(16);
var nX = (10*x)-10;
var nY = (10*y)-10;
var id = x + "," + y;
if (x == colX){
if (y == colY){
var item = document.getElementById("collectable");
item.parentNode.removeChild(item);
wasCollected = true;
newCollectable();
score += 1;
document.getElementById("Score").innerHTML = "Score : " + score;
}
}
body.innerHTML = body.innerHTML + "<div id='" + id + "'; style='position: absolute; left: " + nX + "px; top:" + nY + "px; width: 10px; height: 10px; background-color: #" + r+g+b + "; border: 0; padding: 0; margin: 0;'></div>";
return id;
}
function randInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function newCollectable(){
colX = randInt(1, 59);
colY = randInt(1, 59);
body.innerHTML = body.innerHTML + "<div id='collectable'; style='position: absolute; left: " + (colX*10-10) + "px; top:" + (colY*10-10) + "px; width: 10px; height: 10px; background-color: #f00; border: 0; padding: 0; margin: 0;'></div>";
}
function isBound(x, y){
if (x > 0 && x < 61){
if (y > 0 && y < 61){
return true;
}
}
return false;
}
function die(){
set("data", saves + "|" + score );
location.reload();
}
function update(){
if (paused == false){
if (direction == 1){
posY -= 1;
}else if(direction == 2){
posX += 1;
}else if(direction == 3){
posY += 1;
}else if(direction == 4){
posX -= 1;
}
if (isBound(posX, posY)){
function func(item, index, arr){
var x = item.split(",")[0];
var y = item.split(",")[1];
if(posX == x){
if(posY == y){
die();
}
}
}
snake.forEach(func);
snake.push(newTail(posX, posY));
if(wasCollected == false){
var rem = snake.shift();
var remObj = document.getElementById(rem);
remObj.parentNode.removeChild(remObj);
}else{
wasCollected = false;
}
}else{
die();
}
}
}
function keyDown(event){
if (event.key == "w"){
direction = 1;
}else if(event.key == "d"){
direction = 2;
}else if(event.key == "s"){
direction = 3;
}else if(event.key == "a"){
direction = 4;
}else if(event.key == "p"){
if (paused == true){
paused = false;
document.getElementById("PauseScreen").style.display = "none";
}else{
paused = true;
document.getElementById("PauseScreen").style.display = "";
}
}
}
function loadLeaderboard(){
if (get("data") != null){
saves = get("data");
function func(item, index, arr){
document.getElementById("Scoreboard").innerHTML += '<div><h2 id="' + item + '"; style="text-align: center; font-size: 20px; padding: 0; margin: 0; border: 0;">' + item.toString() + '</h2></div>';
}
saves.split("|").forEach(func);
}
}
function start(){
newCollectable();
snake.push(newTail(10, 15));
snake.push(newTail(11, 15));
snake.push(newTail(12, 15));
setTimeout(loadLeaderboard, 100);
setInterval(update, 100);
}
start();
</script>
</div>
<div id="PauseScreen"style="position: relative; display: none; width: 500px; margin-left: 50%; right: 250px;">
<h2 style="text-align: center; color: #f00; ">Game Paused</h2>
</div>
<div style="margin: 0 40px; width: calc(100% - 80px); background-color: #777;">
<h3 style="text-align: center; font-size: 25px; color: #0f0; padding: 0; margin: 0; border: 0;">LEADERBOARD</h3>
</div>
<hr style="margin: 0px; width:calc(100% - 82px);" />
<div id="Scoreboard" style="margin: 0 40px; width: calc(100% - 80px); background-color: #777;"></div>
<h3 style="position: absolute; right: 10px; bottom: 3px; color: #fff;">Designed by Derek in California</h3>
</body>
</html>
+178
View File
@@ -0,0 +1,178 @@
:root {
--Mistox-Dark: #2C0703;
--Mistox-Medium: #890620;
--Mistox-Light: #B6465F;
--Mistox-Bright: #FC440F;
--Mistox-Offset: #443B75;
--Mistox-Background: #320000;
--Mistox-White: #FFF;
--Mistox-Black: #000;
}
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
main {
background-color: #000000;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='49' viewBox='0 0 28 49'%3E%3Cg fill-rule='evenodd'%3E%3Cg id='hexagons' fill='%23ff0000' fill-opacity='0.2' fill-rule='nonzero'%3E%3Cpath d='M13.99 9.25l13 7.5v15l-13 7.5L1 31.75v-15l12.99-7.5zM3 17.9v12.7l10.99 6.34 11-6.35V17.9l-11-6.34L3 17.9zM0 15l12.98-7.5V0h-2v6.35L0 12.69v2.3zm0 18.5L12.98 41v8h-2v-6.85L0 35.81v-2.3zM15 0v7.5L27.99 15H28v-2.31h-.01L17 6.35V0h-2zm0 49v-8l12.99-7.5H28v2.31h-.01L17 42.15V49h-2z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}
#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
.blazor-error-boundary {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
padding: 1rem 1rem 1rem 3.7rem;
color: white;
}
.blazor-error-boundary::after {
content: "An error has occurred."
}
/* CSS used for the Account Activity Pages */
.center {
position: relative;
left: 50%;
top: 50vh;
transform: translateY(-50%) translateX(-50%);
}
.horizontal-center {
position: relative;
left: 50%;
transform: translateX(-50%);
}
.vertical-center {
position: relative;
top: 50vh;
transform: translateY(-50%);
}
.background-border {
border: var(--Mistox-Background) 2px solid;
border-radius: 6px;
}
.big-frame {
background-color: var(--Mistox-Black);
padding: 4px;
max-width: 400px;
color: var(--Mistox-White);
transition-duration: 1s;
}
.big-frame h3{
margin: 15px 0 30px 0;
color: var(--Mistox-White);
text-align: center;
}
.big-frame h2{
text-align: center;
position: relative;
margin: 0;
top: -20px;
font-size: 15px;
color: var(--Mistox-Bright);
}
.big-frame .frame-item label{
position: relative;
padding: 10px 0;
font-size: 16px;
color: var(--Mistox-White);
pointer-events: none;
transition: .5s;
top: -70px;
left: 20px;
}
.big-frame .frame-item input:autofill,
.big-frame .frame-item input:-webkit-autofill,
.big-frame .frame-item input {
position: relative;
width: calc(100% - 40px);
margin: 0 20px;
padding: 10px 0;
font-size: 15px;
color: var(--Mistox-White);
margin-bottom: 30px;
border: none;
border-bottom: 1px solid var(--Mistox-White);
outline: none;
background: transparent;
}
.big-frame .frame-item input:focus ~ label,
.big-frame .frame-item input:not(:placeholder-shown) ~ label {
top: -95px;
left: 10px;
color: var(--Mistox-Light);
font-size: 12px;
}
.flex-row{
display: flex;
flex-direction: row;
justify-content: space-around;
}
.sub-frame {
text-align: center;
padding: 1px 0;
}
.submit{
position: relative;
padding: 10px 20px;
color: var(--Mistox-Black);
background-color: var(--Mistox-Light);
font-size: 16px;
text-decoration: none;
text-transform: uppercase;
overflow: hidden;
transition: transform 0.3s ease, box-shadow 0.5s ease;
letter-spacing: 4px;
border: 1px solid var(--Mistox-Light);
margin: auto;
border-radius: 5px;
}
.submit:hover {
background-color: var(--Mistox-Light);
color: var(--Mistox-White);
box-shadow: 4px 3px 6px var(--Mistox-Dark);
}
.submit:active {
transform: translate( 4px, 2px );
background-color: var(--Mistox-Dark);
border: none;
color: var(--Mistox-White);
box-shadow: none;
}
ul {
list-style: none;
color: var(--Mistox-Bright);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

+46
View File
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>MistoxNet</title>
<base href="/" />
<link href="MistoxWebsite.Client.styles.css" rel="stylesheet">
<link href="css/app.css" rel="stylesheet">
<script src="js/screenwidth.js"></script>
<script>
PaymentLoaded = async function () {
var iframe;
while (iframe == null) {
await new Promise(r => setTimeout(r, 50));
iframe = document.getElementById("PaymentFrame");
}
window.onresize = function () {
iframe.style.height = iframe.contentWindow.document.body.scrollHeight + 50 + 'px';
}
window.onchange = function () {
iframe.style.height = iframe.contentWindow.document.body.scrollHeight + 50 + 'px';
}
iframe.onload = function () {
iframe.style.height = iframe.contentWindow.document.body.scrollHeight + 50 + 'px';
}
for (var i = 0; i < 2000; i++) {
await new Promise(r => setTimeout(r, 100));
iframe.style.height = iframe.contentWindow.document.body.scrollHeight + 50 + 'px';
}
}
</script>
</head>
<body style="border: 0; padding: 0; margin: 0;">
<div id="app"></div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.webassembly.js"></script>
</body>
</html>
+6
View File
@@ -0,0 +1,6 @@
window.getWindowSize = function() {
return {
width: window.innerWidth,
height: window.innerHeight
};
};