This commit is contained in:
+285
@@ -0,0 +1,285 @@
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Security.Claims;
|
||||
using BoredCareers.Services;
|
||||
using BoredCareers.Services.DatabaseService;
|
||||
using BoredCareers.Entities;
|
||||
|
||||
namespace BoredCareers.Controllers {
|
||||
[ApiController]
|
||||
[Route("api/account/[controller]")]
|
||||
public class AuthenticationController : MistoxControllerBase {
|
||||
|
||||
EmailService _emailContext;
|
||||
|
||||
public AuthenticationController(DatabaseService db, EmailService emailContext) : base(db) {
|
||||
_emailContext = emailContext;
|
||||
}
|
||||
|
||||
[Route("login")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<Account>> Login([FromForm] string UserName, [FromForm] string PasswordHash, [FromForm] bool StayLoggedIn) {
|
||||
try {
|
||||
Account? test = await _databaseService.GetAccount(UserName.ToLower());
|
||||
if (test != null) {
|
||||
if (test.EmailVerified == true) {
|
||||
if (test.FailedPasswordLock) {
|
||||
if (test.CurrentPasswordAttempts >= test.PasswordAttempts) {
|
||||
return new Account() { Error = "Too many failed password attempts. Please reset your password" };
|
||||
}
|
||||
}
|
||||
if (BCrypt.Net.BCrypt.Verify(PasswordHash, test.PasswordHash)) {
|
||||
test.CurrentPasswordAttempts = 0;
|
||||
await _databaseService.SetAccount(test);
|
||||
|
||||
List<Claim> claims = new List<Claim>() {
|
||||
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 = StayLoggedIn, // Is set from the StayLoggedIn
|
||||
}
|
||||
);
|
||||
return test;
|
||||
}
|
||||
else {
|
||||
test.CurrentPasswordAttempts += 1;
|
||||
await _databaseService.SetAccount(test);
|
||||
return new Account() { Error = "Wrong password" };
|
||||
}
|
||||
}
|
||||
else {
|
||||
await SendVerify(test.UserName);
|
||||
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 };
|
||||
}
|
||||
}
|
||||
|
||||
[Route("register")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<Account>> Register([FromForm] string Email, [FromForm] string UserName, [FromForm] string PasswordHash) {
|
||||
try {
|
||||
if (await _databaseService.GetAccount(UserName.ToLower()) == null) {
|
||||
if (await _databaseService.GetAccount(Email.ToLower()) == null) {
|
||||
Account? created = new Account() {
|
||||
UserName = UserName.ToLower(),
|
||||
Email = Email.ToLower(),
|
||||
EmailVerified = false,
|
||||
PasswordHash = BCrypt.Net.BCrypt.HashPassword(PasswordHash),
|
||||
};
|
||||
await _databaseService.SetAccount(created);
|
||||
created = await _databaseService.GetAccount(Email.ToLower());
|
||||
if (created != null) {
|
||||
await SendVerify(created.UserName);
|
||||
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 };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Route("changepassword")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<bool>> ChangePassword([FromForm] string OldPassword, [FromForm] string NewPassword) {
|
||||
try {
|
||||
if (isLoggedIn()) {
|
||||
Account user = await getLoggedInUser();
|
||||
if (BCrypt.Net.BCrypt.Verify(OldPassword, user.PasswordHash)) {
|
||||
user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(NewPassword);
|
||||
user.CurrentPasswordAttempts = 0;
|
||||
await _databaseService.SetAccount(user);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[Route("toggleaccountlock")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<string>> ToggleAccountLock([FromForm] bool AccountLock) {
|
||||
try {
|
||||
if (isLoggedIn()) {
|
||||
Account user = await getLoggedInUser();
|
||||
user.FailedPasswordLock = AccountLock;
|
||||
user.CurrentPasswordAttempts = 0;
|
||||
await _databaseService.SetAccount(user);
|
||||
return "Account Lock Status Updated";
|
||||
}
|
||||
return "Unknown Error Occurred";
|
||||
} catch (Exception ex) {
|
||||
return ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
[Route("get")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<Account?>> Get() {
|
||||
try {
|
||||
if (isLoggedIn()) {
|
||||
return await getLoggedInUser();
|
||||
}
|
||||
return Ok();
|
||||
} catch {
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
|
||||
[Route("logout")]
|
||||
[HttpPost]
|
||||
public async Task Logout() {
|
||||
await HttpContext.SignOutAsync();
|
||||
}
|
||||
|
||||
[Route("sendverifyemail")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<string>> SendVerify([FromForm] string UserName) {
|
||||
try {
|
||||
string key = "v" + 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 _databaseService.GetAccount(UserName.ToLower());
|
||||
if (test != null) {
|
||||
test.EmailToken = Guid.NewGuid().ToString();
|
||||
await _databaseService.SetAccount(test);
|
||||
|
||||
string EmailContents = EmailService.VerifyEmailEmail;
|
||||
EmailContents = Substitue(EmailContents, "@UserName", UserName);
|
||||
EmailContents = Substitue(EmailContents, "@UserName", UserName);
|
||||
EmailContents = Substitue(EmailContents, "@VerifyPassword", test.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";
|
||||
}
|
||||
}
|
||||
|
||||
[Route("verifyemail")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<bool>> VerifyEmail([FromForm] string UserName, [FromForm] string EmailToken) {
|
||||
try {
|
||||
Account? test = await _databaseService.GetAccount(UserName.ToLower());
|
||||
if (test != null) {
|
||||
if (!string.IsNullOrEmpty(test.EmailToken) && test.EmailToken == EmailToken) {
|
||||
test.EmailToken = "";
|
||||
test.EmailVerified = true;
|
||||
await _databaseService.SetAccount(test);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[Route("sendresetpassword")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<string>> ResetPassword([FromForm] string Email) {
|
||||
try {
|
||||
string key = "p" + 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 _databaseService.GetAccount(Email.ToLower());
|
||||
if (test != null) {
|
||||
test.EmailToken = Guid.NewGuid().ToString();
|
||||
await _databaseService.SetAccount(test);
|
||||
|
||||
string EmailContents = EmailService.ResetPasswordEmail;
|
||||
EmailContents = Substitue(EmailContents, "@UserName", test.UserName);
|
||||
EmailContents = Substitue(EmailContents, "@UserName", test.UserName);
|
||||
EmailContents = Substitue(EmailContents, "@ResetPassWord", test.EmailToken);
|
||||
|
||||
string result = _emailContext.Send(test.Email, EmailService.VerifyEmailSubject, EmailContents);
|
||||
_emailContext._SentEmails.Add(key, DateTime.Now);
|
||||
return result;
|
||||
}
|
||||
return "Account Not Found";
|
||||
} catch (Exception e) {
|
||||
Console.WriteLine("EmailService Error: " + e.ToString());
|
||||
return "The connection couldn't be established to the email server";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Route("resetpassword")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<bool>> ResetPwdVerify([FromForm] string UserName, [FromForm] string NewPassword, [FromForm] string ResetToken) {
|
||||
try {
|
||||
Account? test = await _databaseService.GetAccount(UserName.ToLower());
|
||||
if (test != null && !string.IsNullOrEmpty(test.EmailToken)) {
|
||||
if (!string.IsNullOrEmpty(test.EmailToken) && test.EmailToken == ResetToken) {
|
||||
test.CurrentPasswordAttempts = 0;
|
||||
test.EmailToken = "";
|
||||
test.PasswordHash = BCrypt.Net.BCrypt.HashPassword(NewPassword);
|
||||
await _databaseService.SetAccount(test);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[Route("delete")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<bool>> delete([FromForm] string Password) {
|
||||
try {
|
||||
if (isLoggedIn()) {
|
||||
Account user = await getLoggedInUser();
|
||||
if (BCrypt.Net.BCrypt.Verify(Password, user.PasswordHash)) {
|
||||
await _databaseService.DeleteAccount(user.ID);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using BoredCareers.Entities;
|
||||
using BoredCareers.Services.DatabaseService;
|
||||
|
||||
namespace BoredCareers.Controllers {
|
||||
[ApiController]
|
||||
[Route("api/cart/[controller]")]
|
||||
public class CartController : MistoxControllerBase {
|
||||
|
||||
CartController(DatabaseService db) : base(db) { }
|
||||
|
||||
[Route("get")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<Cart[]>> GetCart() {
|
||||
try {
|
||||
if (isLoggedIn()) {
|
||||
return Ok(await _databaseService.GetCart(getLoggedInUserID()));
|
||||
}
|
||||
return StatusCode(500);
|
||||
} catch {
|
||||
return StatusCode(500);
|
||||
}
|
||||
}
|
||||
|
||||
[Route("add")]
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> AddCart([FromBody] Cart cart) {
|
||||
try {
|
||||
if (isLoggedIn()) {
|
||||
cart.AccountID = getLoggedInUserID();
|
||||
await _databaseService.AddToCart(cart);
|
||||
return Ok();
|
||||
}
|
||||
return StatusCode(500);
|
||||
} catch {
|
||||
return StatusCode(500);
|
||||
}
|
||||
}
|
||||
|
||||
[Route("remove")]
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> RemoveCart([FromBody] Cart cart) {
|
||||
try {
|
||||
if (isLoggedIn()) {
|
||||
cart.AccountID = getLoggedInUserID();
|
||||
await _databaseService.RemoveFromCart(cart);
|
||||
return Ok();
|
||||
}
|
||||
return StatusCode(500);
|
||||
} catch {
|
||||
return StatusCode(500);
|
||||
}
|
||||
}
|
||||
|
||||
[Route("clear")]
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> ClearCart() {
|
||||
try {
|
||||
if (isLoggedIn()) {
|
||||
await _databaseService.ClearCart(getLoggedInUserID());
|
||||
return Ok();
|
||||
}
|
||||
return StatusCode(500);
|
||||
} catch {
|
||||
return StatusCode(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using BoredCareers.Entities;
|
||||
using BoredCareers.Services.DatabaseService;
|
||||
|
||||
namespace BoredCareers.Controllers {
|
||||
|
||||
public class MistoxControllerBase : ControllerBase {
|
||||
|
||||
public DatabaseService _databaseService;
|
||||
|
||||
public MistoxControllerBase(DatabaseService databaseService) {
|
||||
_databaseService = databaseService;
|
||||
}
|
||||
|
||||
public bool isLoggedIn() {
|
||||
if (User.Identity != null && User.Identity.IsAuthenticated) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getLoggedInUserID() {
|
||||
return Convert.ToInt32(User.FindFirst("ID")?.Value);
|
||||
}
|
||||
|
||||
public async Task<Account> getLoggedInUser() {
|
||||
try {
|
||||
Account? test = await _databaseService.GetAccount(getLoggedInUserID());
|
||||
if (test != null) {
|
||||
return test;
|
||||
}
|
||||
return new Account();
|
||||
} catch {
|
||||
return new Account();
|
||||
}
|
||||
}
|
||||
|
||||
public 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;
|
||||
}
|
||||
|
||||
public 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using BoredCareers.Controllers.Payment;
|
||||
using BoredCareers.Services.DatabaseService;
|
||||
using BoredCareers.Entities;
|
||||
|
||||
namespace BoredCareers.Controllers {
|
||||
[ApiController]
|
||||
[Route("api/payment/[controller]")]
|
||||
public class PaymentController : MistoxControllerBase {
|
||||
|
||||
IPayment _paymentService;
|
||||
|
||||
public PaymentController(DatabaseService db) : base(db) {
|
||||
if (IPayment._PaymentType == PaymentType.StripeIntent) {
|
||||
_paymentService = new StripeIntent(_databaseService);
|
||||
} else {
|
||||
// Fallback
|
||||
_paymentService = new StripeIntent(_databaseService);
|
||||
}
|
||||
// Add new payment plugins here
|
||||
}
|
||||
|
||||
[Route("getcheckouttoken")]
|
||||
[HttpPost]
|
||||
public async Task<string> GetCheckoutToken() {
|
||||
string OrderNumber = Guid.NewGuid().ToString().Substring(0, 10);
|
||||
if (isLoggedIn()) {
|
||||
Cart[] carts = await _databaseService.GetCart(getLoggedInUserID());
|
||||
(bool, string) PaymentResponse = await _paymentService.TryGetCheckoutToken(OrderNumber, getLoggedInUserID(), carts);
|
||||
if (PaymentResponse.Item1) {
|
||||
// Returns client secret
|
||||
return PaymentResponse.Item2;
|
||||
} else {
|
||||
Console.WriteLine("An error has occured in the payment plugin\n\n");
|
||||
Console.WriteLine(PaymentResponse.Item2);
|
||||
Console.WriteLine("\n");
|
||||
return "An error has occured in the payment plugin";
|
||||
}
|
||||
}
|
||||
return "You must be logged in";
|
||||
}
|
||||
|
||||
[Route("getpublickey")]
|
||||
[HttpPost]
|
||||
public IActionResult GetPublicKey() {
|
||||
try {
|
||||
return Ok(IPayment._PublicKey);
|
||||
} catch (Exception ex) {
|
||||
return NotFound(ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[Route("response")]
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> paymentWebhook() {
|
||||
try {
|
||||
string body = await new StreamReader(Request.Body).ReadToEndAsync();
|
||||
await _paymentService.ValidatePurchase(body, Request.Headers["Stripe-Signature"].ToString());
|
||||
return Ok();
|
||||
} catch (Exception ex) {
|
||||
return NotFound(ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using BoredCareers.Entities;
|
||||
|
||||
namespace BoredCareers.Controllers.Payment {
|
||||
|
||||
public interface IPayment {
|
||||
|
||||
public static PaymentType _PaymentType;
|
||||
public static string _EndpointSecret = "";
|
||||
public static string _PublicKey = "";
|
||||
|
||||
public Task<(bool, string)> TryGetCheckoutToken(string OrderNumber, int userID, Cart[] cart);
|
||||
public Task ValidatePurchase(string WebHookData, string Headers);
|
||||
|
||||
}
|
||||
|
||||
public enum PaymentType {
|
||||
StripeIntent
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
using BoredCareers.Controllers.Payment;
|
||||
using BoredCareers.Services.DatabaseService;
|
||||
using BoredCareers.Entities;
|
||||
|
||||
namespace BoredCareers.Controllers {
|
||||
|
||||
public class StripeIntent : IPayment {
|
||||
|
||||
DatabaseService _databaseService;
|
||||
|
||||
public StripeIntent(DatabaseService databaseService) {
|
||||
_databaseService = databaseService;
|
||||
}
|
||||
|
||||
public async Task<(bool, string)> TryGetCheckoutToken(string OrderNumber, int userID, Cart[] cart) {
|
||||
try {
|
||||
// build Recipt and calculate Tax
|
||||
var options = new Stripe.Tax.CalculationCreateOptions {
|
||||
Currency = "usd",
|
||||
CustomerDetails = new Stripe.Tax.CalculationCustomerDetailsOptions {
|
||||
AddressSource = "billing",
|
||||
},
|
||||
Expand = new List<string>() { "line_items" },
|
||||
LineItems = new List<Stripe.Tax.CalculationLineItemOptions>()
|
||||
};
|
||||
|
||||
List<int> prods = new List<int>();
|
||||
|
||||
// Add items to receipt
|
||||
int subtotal = 0;
|
||||
foreach (Cart items in cart) {
|
||||
Product? product = await _databaseService.GetProduct(items.ProductID);
|
||||
if (product != null) {
|
||||
prods.Add(product.ID);
|
||||
if (product != null) {
|
||||
subtotal += product.Cost;
|
||||
options.LineItems.Add(new Stripe.Tax.CalculationLineItemOptions {
|
||||
Amount = product.Cost,
|
||||
TaxCode = "txcd_10201000", // Tax code for downloadable digital games
|
||||
Quantity = 1,
|
||||
Reference = product.Name,
|
||||
TaxBehavior = "exclusive"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var service = new Stripe.Tax.CalculationService();
|
||||
Stripe.Tax.Calculation result = service.Create(options);
|
||||
|
||||
string csv = "";
|
||||
foreach (int cur in prods) {
|
||||
csv = csv + cur + ",";
|
||||
}
|
||||
|
||||
// Crate Payment Intent
|
||||
Stripe.PaymentIntentCreateOptions paymentIntent = new Stripe.PaymentIntentCreateOptions() {
|
||||
Amount = result.AmountTotal,
|
||||
Currency = "usd",
|
||||
Metadata = new Dictionary<string, string> {
|
||||
{ "ordernumber", OrderNumber },
|
||||
{ "user", userID.ToString() },
|
||||
{ "products", csv },
|
||||
{ "subtotal", subtotal.ToString() },
|
||||
{ "total", result.AmountTotal.ToString() }
|
||||
},
|
||||
StatementDescriptor = "Mistox.Net #" + OrderNumber
|
||||
};
|
||||
|
||||
Stripe.PaymentIntentService intentService = new Stripe.PaymentIntentService();
|
||||
Stripe.PaymentIntent x = await intentService.CreateAsync(paymentIntent);
|
||||
|
||||
return (true, x.ClientSecret);
|
||||
} catch (Exception e) {
|
||||
return (false, e.ToString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public async Task ValidatePurchase(string WebHookData, string Headers) {
|
||||
Stripe.Event e = Stripe.EventUtility.ConstructEvent( WebHookData, Headers, IPayment._EndpointSecret );
|
||||
if (e.Type == "payment_intent.succeeded") {
|
||||
// Extract Data from payment confirm
|
||||
Stripe.PaymentIntent intent = (Stripe.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
|
||||
await _databaseService.ClearCart(userID);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+143
@@ -0,0 +1,143 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using BoredCareers.Services.DatabaseService;
|
||||
using BoredCareers.Entities;
|
||||
|
||||
namespace BoredCareers.Controllers {
|
||||
[ApiController]
|
||||
[Route("api/product/[controller]")]
|
||||
public class ProductController : MistoxControllerBase {
|
||||
|
||||
public ProductController(DatabaseService db) : base(db) { }
|
||||
|
||||
[Route("set")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<bool>> CreateProduct([FromForm] Product obj, [FromForm] IFormFile[] images) {
|
||||
try {
|
||||
if (isLoggedIn()) {
|
||||
Account user = await getLoggedInUser();
|
||||
if (user.Role == "Admin") {
|
||||
List<ProductImage> building = new List<ProductImage>();
|
||||
foreach (var file in images) {
|
||||
using (var stream = new MemoryStream()) {
|
||||
await file.CopyToAsync(stream);
|
||||
var bytes = stream.ToArray();
|
||||
|
||||
// Convert to your image model or whatever your logic is
|
||||
ProductImage img = new ProductImage { Image = bytes, Name = file.FileName };
|
||||
building.Add(img);
|
||||
}
|
||||
}
|
||||
obj.Images = building.ToArray();
|
||||
await _databaseService.SetProduct(obj);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
Console.WriteLine(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[Route("get")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<Product>> GetProduct([FromForm] int productID) {
|
||||
try {
|
||||
Product? product = await _databaseService.GetProduct(productID);
|
||||
if (product != null) {
|
||||
return product;
|
||||
}
|
||||
else {
|
||||
return NotFound();
|
||||
}
|
||||
} catch {
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[Route("getall")]
|
||||
[HttpPost]
|
||||
public async Task<Product[]> GetAllProducts() {
|
||||
try {
|
||||
return await _databaseService.GetAllProducts();
|
||||
} catch {
|
||||
return Array.Empty<Product>();
|
||||
}
|
||||
}
|
||||
|
||||
[Route("delete")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<bool>> DeleteProduct([FromForm] int productID) {
|
||||
try {
|
||||
if (isLoggedIn()) {
|
||||
Account user = await getLoggedInUser();
|
||||
if (user.Role == "Admin") {
|
||||
await _databaseService.DeleteProduct(productID);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
[Route("getimage")]
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> GetProductImage([FromForm] int ProductID, [FromForm] int ImageID) {
|
||||
try {
|
||||
ProductImage? img = await _databaseService.GetImage(ProductID, ImageID);
|
||||
if (img != null) {
|
||||
return File(img.Image, "Image/*");
|
||||
}
|
||||
else {
|
||||
return NotFound();
|
||||
}
|
||||
} catch {
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
|
||||
[Route("getowned")]
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<Receipt[]>> GetOwnedProduct() {
|
||||
try {
|
||||
if (isLoggedIn()) {
|
||||
Receipt[] returned = await _databaseService.GetAllReceipts(getLoggedInUserID());
|
||||
return returned;
|
||||
}
|
||||
return new Receipt[0];
|
||||
} catch {
|
||||
return new Receipt[0];
|
||||
}
|
||||
}
|
||||
|
||||
[Route("download")]
|
||||
[HttpGet]
|
||||
public async Task<ActionResult> Download([FromQuery] string Product) {
|
||||
try {
|
||||
if (isLoggedIn()) {
|
||||
Product[] games = await _databaseService.GetAllProducts();
|
||||
foreach (Product product in games) {
|
||||
if (contains(Product, product.URL)) {
|
||||
Receipt? receipt = await _databaseService.GetReceipt(getLoggedInUserID(), product.ID);
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user