Init Commit
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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" } );
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user