Compare commits

..

34 Commits

Author SHA1 Message Date
derek 64cc5066af Update Comment for angular sizes 2025-06-19 19:51:56 -07:00
derek ddb05c305c Update comment 2025-06-19 19:45:07 -07:00
derek b9cb93071d Turn off AOT as its the best option for produciton 2025-06-19 19:19:30 -07:00
derek ff91ff9109 Turn all optimizations back on for speed test 2025-06-19 18:56:57 -07:00
derek 57dca6974a For test with no Optimizations 2025-06-19 18:50:55 -07:00
derek d83ba35a84 Turn AOT back off 2025-06-19 18:45:57 -07:00
derek 7160515121 Try running AOT compile again 2025-06-19 18:19:31 -07:00
derek 66db26c74c Remove App.css 2025-06-19 18:13:16 -07:00
derek 4902f9c6ce Dont cut anything that is the app 2025-06-19 18:08:27 -07:00
derek 16a9c5ec5f Disable more trimmings 2025-06-19 18:03:48 -07:00
derek e1d3908e29 Turn off linking for the full Newtonsoft.Json 2025-06-19 17:58:18 -07:00
derek ea9d1fa24f Add more to newtonsoft ignores 2025-06-19 17:51:46 -07:00
derek 4f6fc16494 Turn linking back on with Newtonsoft not trimmed 2025-06-19 17:46:54 -07:00
derek 123f739b61 Turn off linking 2025-06-19 17:39:25 -07:00
derek 0cdcf9af71 Trim less 2025-06-19 17:31:50 -07:00
derek 59d6bb1ef1 Turn off AOT compile for blazor 2025-06-19 17:26:28 -07:00
derek 60d9b844fb Add comments to dockerfile 2025-06-19 17:09:41 -07:00
derek 1a08e99c6b . 2025-06-19 16:59:13 -07:00
derek 2e8893b240 add python to build container 2025-06-19 16:58:19 -07:00
derek d0af6ba73c update docker for wasm 2025-06-19 16:52:54 -07:00
derek 059c755d14 Update client to use forms 2025-06-19 16:49:43 -07:00
derek 34d3d047d2 fix namespacing issues 2025-06-19 16:49:34 -07:00
derek a3de3d573a Make api 'FormBody' -> cleaner & smaller dto's 2025-06-19 16:48:52 -07:00
derek bbab4972c3 Update usings for new shared folder 2025-06-19 16:48:16 -07:00
derek 07a1014889 Fix warnings by cleaning CSS 2025-06-19 16:47:23 -07:00
derek 2ce398a8d4 Organize imports file 2025-06-19 16:46:53 -07:00
derek fcf64f335d Remove non-essential website pages 2025-06-19 16:46:39 -07:00
derek c873f473c8 Delete Launch Settings 2025-06-19 16:46:18 -07:00
derek f110ad8d27 Modify GitIgnore 2025-06-19 16:46:06 -07:00
derek 412624a93c Split apart the DTO from the Database Objects 2025-06-19 10:40:26 -07:00
derek.holloway e88c7111e6 add lauch task for F5 2025-06-18 13:47:17 -07:00
derek.holloway 7c3ac165b7 Update .gitignore 2025-06-18 13:47:09 -07:00
derek.holloway b37dcf7c7d Make overscroll black 2025-06-18 13:38:43 -07:00
derek.holloway f0a7946a52 Enable Publish Speed Improvements 2025-06-18 13:38:33 -07:00
48 changed files with 596 additions and 1363 deletions
+2 -2
View File
@@ -2,5 +2,5 @@
**/obj
.git
.env
.vscode
data
data
Properties
+25
View File
@@ -0,0 +1,25 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "dotnet: build",
"program": "${workspaceFolder}/src/MistoxWebsite.Server/bin/Debug/net9.0/MistoxWebsite.Server.dll",
"args":[],
"cwd": "${workspaceFolder}/src/MistoxWebsite.Server/",
"stopAtEntry": false,
"serverReadyAction":{
"action": "openExternally",
"killOnServerStop": false
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development",
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
}
]
}
+7
View File
@@ -5,6 +5,13 @@ WORKDIR /src
# Copy all projects
COPY ["src", "."]
# Needed for AOT Compiling wasm
RUN dotnet workload install wasm-tools
# Needed for compression of AOT files
RUN apt update
RUN apt install -y python3
# Restore the Server
RUN dotnet restore 'MistoxWebsite.Server/MistoxWebsite.Server.csproj'
+4 -1
View File
@@ -24,4 +24,7 @@ Store Catalog
Add to cart wraps text when screen is too small
Program
Probably need to turn on cors at some point
Probably need to turn on cors at some point
ProductController
No way to download products
-2
View File
@@ -1,2 +0,0 @@
/* This file is needed for compile for some reason */
/* Dont delete this file */
@@ -0,0 +1,4 @@
<linker>
<assembly fullname="Newtonsoft.Json" preserve="all" />
<assembly fullname="MistoxWebsite.Client" preserve="all" />
</linker>
@@ -4,19 +4,26 @@
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<!-- Without Optimizations 3.92MB Initial Download / 302Kb home page load after -->
<!-- All Optimizations Without AOT 3.27MB Initial Download / 302Kb home page load after -->
<!-- All Optimizations With AOT 7.44MB Initial Download / 303Kb home page load after-->
<!-- Angular with ASPNET backend 0.49Kb Inital Download / 0.49Kb home page load after -->
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>link</TrimMode>
<RunAOTCompilation>false</RunAOTCompilation>
<InvariantGlobalization>true</InvariantGlobalization>
<BlazorEnableCompression>true</BlazorEnableCompression>
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
<StripSymbols>true</StripSymbols>
</PropertyGroup>
<!-- Retain important files on trimming -->
<ItemGroup>
<None Remove="App.razor.css" />
</ItemGroup>
<ItemGroup>
<Content Include="App.razor.css">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<TrimmerRootDescriptor Include="ILLink.Descriptors.xml" />
</ItemGroup>
<!-- Packages -->
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="9.0.3" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.3" />
@@ -24,6 +31,7 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<!-- Project References -->
<ItemGroup>
<ProjectReference Include="..\MistoxWebsite.Shared\MistoxWebsite.Shared.csproj" />
</ItemGroup>
@@ -34,10 +34,21 @@
}
public async Task TrySendCode() {
Result = "Waiting on response from server";
HttpResponseMessage TestLogin = await Http.PostAsJsonAsync("api/account/sendresetpassword", new Account(){ Email = Email });
Result = await TestLogin.Content.ReadAsStringAsync();
MailAddress addr = new MailAddress(Email);
if ( addr.Address != Email ){
Result = "Enter a valid email address";
}else{
Result = "";
}
if (string.IsNullOrEmpty(Result)){
Dictionary<string, string> formData = new Dictionary<string, string>{
{ "Email", Email }
};
Result = "Waiting on response from server";
HttpResponseMessage TestLogin = await Http.PostAsync("api/account/sendresetpassword", new FormUrlEncodedContent(formData) );
Result = await TestLogin.Content.ReadAsStringAsync();
}
base.StateHasChanged();
}
}
}
@@ -54,34 +54,36 @@
Loading = "Waiting for login response from server";
ReturnURL = string.IsNullOrEmpty(ReturnURL) ? "/" : ReturnURL;
ErrorMsgs = new List<string>();
if( !string.IsNullOrEmpty(UserName) ) {
if( !string.IsNullOrEmpty(Password) ) {
if (Password.Length >= 6 ) {
HttpResponseMessage TestLogin = await Http.PostAsJsonAsync("api/account/login", new MistoxWebsite.Shared.Account(){ UserName = UserName, PasswordHash = Password, EmailVerified = StayLoggedIn });
string result = await TestLogin.Content.ReadAsStringAsync();
Account? user = JsonConvert.DeserializeObject<Account>(result);
if (user == null ) {
ErrorMsgs.Add("No response from the server");
base.StateHasChanged();
return;
}
if ( string.IsNullOrEmpty(user.Error) ) {
ErrorMsgs.Add("Login Success");
Nav.NavigateTo("/", true);
} else {
ErrorMsgs.Add(user.Error);
}
Loading = "";
} else {
ErrorMsgs.Add("Password must be at least 6 Characters long");
}
} else {
ErrorMsgs.Add("The 'password' field is required");
}
} else{
if( string.IsNullOrEmpty(UserName) ) {
ErrorMsgs.Add("The 'username' field is required");
}
if( string.IsNullOrEmpty(Password) ) {
ErrorMsgs.Add("The 'password' field is required");
}
if (Password.Length < 6 ) {
ErrorMsgs.Add("Password must be at least 6 Characters long");
}
if (ErrorMsgs.Count == 0){
Dictionary<string, string> formData = new Dictionary<string, string>{
{ "UserName", UserName },
{ "PasswordHash", Password },
{ "StayLoggedIn", StayLoggedIn.ToString() }
};
HttpResponseMessage TestLogin = await Http.PostAsync("api/account/login", new FormUrlEncodedContent(formData) );
string result = await TestLogin.Content.ReadAsStringAsync();
Account? user = JsonConvert.DeserializeObject<Account>(result);
if (user == null ) {
ErrorMsgs.Add("No response from the server");
base.StateHasChanged();
return;
}
if ( string.IsNullOrEmpty(user.Error) ) {
ErrorMsgs.Add("Login Success");
Nav.NavigateTo(ReturnURL, true);
} else {
ErrorMsgs.Add(user.Error);
}
}
Loading = "";
base.StateHasChanged();
}
@@ -52,63 +52,41 @@
}
}
public bool CheckEmail(string email ) {
int ATcount = 0;
int DOTcount = 0;
char[] cmail = email.ToArray();
foreach(char cur in cmail ) {
if(cur == '@' ) {
ATcount += 1;
}else if(cur == '.' ) {
DOTcount += 1;
}
}
if (ATcount == 1 && DOTcount >= 1 ) {
return true;
}
return false;
}
public async Task TryRegister() {
Loading = "Waiting for a response from the server";
ReturnURL = string.IsNullOrEmpty(ReturnURL) ? "/" : ReturnURL;
ErrorMsgs = new List<string>();
if ( !string.IsNullOrEmpty(Email) ){
if( CheckEmail( Email ) ) {
if( !string.IsNullOrEmpty(UserName) ) {
if( !string.IsNullOrEmpty(Password) ) {
if (Password.Length >= 6 ) {
HttpResponseMessage TestRegister = await Http.PostAsJsonAsync("api/account/register", new Account(){
UserName = UserName,
Email = Email,
PasswordHash = Password,
EmailVerified = false,
});
Account? user = await TestRegister.Content.ReadFromJsonAsync<Account>();
if ( string.IsNullOrEmpty(user?.Error) ) {
ErrorMsgs.Add("Register Success");
Nav.NavigateTo("/", true);
} else {
ErrorMsgs.Add( user.Error );
}
Loading = "";
}else{
ErrorMsgs.Add("Password must be at least 6 Characters long");
}
}else{
ErrorMsgs.Add("The 'password' field is required");
}
}else{
ErrorMsgs.Add("The 'username' field is required");
}
}else{
ErrorMsgs.Add("Please check your email address");
}
}else{
MailAddress addr = new MailAddress(Email);
if ( addr.Address != Email ){
ErrorMsgs.Add("Please check your email address");
}
if (Password.Length < 6 ) {
ErrorMsgs.Add("Password must be at least 6 Characters long");
}
if( string.IsNullOrEmpty(UserName) ) {
ErrorMsgs.Add("The 'username' field is required");
}
if( string.IsNullOrEmpty(Password) ) {
ErrorMsgs.Add("The 'password' field is required");
}
if ( string.IsNullOrEmpty(Email) ){
ErrorMsgs.Add("The 'email' field is required");
}
if (ErrorMsgs.Count == 0){
Dictionary<string, string> formData = new Dictionary<string, string>{
{ "Email", Email },
{ "UserName", UserName },
{ "PasswordHash", Password },
};
HttpResponseMessage TestRegister = await Http.PostAsync("api/account/register", new FormUrlEncodedContent(formData) );
Account? user = await TestRegister.Content.ReadFromJsonAsync<Account>();
if ( string.IsNullOrEmpty(user?.Error) ) {
ErrorMsgs.Add("Register Success");
Nav.NavigateTo(ReturnURL, true);
} else {
ErrorMsgs.Add( user.Error );
}
}
Loading = "";
base.StateHasChanged();
}
@@ -38,7 +38,6 @@
[Parameter]
[SupplyParameterFromQuery]
public string ResetPwd { get; set; } = "";
public string NewPassword{ get; set; } = "";
public string RepeatPassword{ get; set; } = "";
@@ -52,24 +51,29 @@
protected async Task TryChange() {
Result = "Waiting on response from server";
if (NewPassword.Length >= 6){
if (NewPassword == RepeatPassword){
HttpResponseMessage TestLogin = await Http.PostAsJsonAsync("api/account/resetpassword", new Account(){ UserName = UserName, PasswordHash = NewPassword, Error = ResetPwd });
string result = await TestLogin.Content.ReadAsStringAsync();
bool success = result == "true" ? true : false;
if (success){
Result = "Password changed successfully";
Thread.Sleep(2000);
Nav.NavigateTo("/", true);
}else{
Result = "Something is wrong";
}
}else{
Result = "Passwords must match";
}
}else{
if (NewPassword != RepeatPassword){
Result = "Passwords must match";
}
if (NewPassword.Length < 6){
Result = "Password must be at least 6 Characters long";
}
if (string.IsNullOrEmpty(Result)){
Dictionary<string, string> formData = new Dictionary<string, string>{
{ "UserName", UserName },
{ "NewPassword", NewPassword },
{ "ResetToken", ResetPwd },
};
HttpResponseMessage TestLogin = await Http.PostAsync("api/account/resetpassword", new FormUrlEncodedContent(formData) );
string result = await TestLogin.Content.ReadAsStringAsync();
bool success = result == "true" ? true : false;
if (success){
Result = "Password changed successfully";
Thread.Sleep(2000);
Nav.NavigateTo("/", true);
}else{
Result = "Something is wrong";
}
}
}
}
@@ -26,7 +26,11 @@
public string Result{ get; set; } = "";
protected override async Task OnInitializedAsync() {
HttpResponseMessage Query = await Http.PostAsJsonAsync("api/account/verifyemail", new Account(){ UserName = UserName, PasswordHash = Guid });
Dictionary<string, string> formData = new Dictionary<string, string>{
{ "UserName", UserName },
{ "EmailToken", Guid },
};
HttpResponseMessage Query = await Http.PostAsync("api/account/verifyemail", new FormUrlEncodedContent(formData) );
bool Answer = await Query.Content.ReadFromJsonAsync<bool>();
if (Answer == true ) {
Result = "Verified Email Successfully";
@@ -41,7 +41,7 @@
@code {
public MistoxWebsite.Shared.Account? _account = null;
public MistoxWebsite.Shared.Database.Account? _account = null;
public int MaxFailedLogin = 0;
public bool FailedLoginToggle = false;
@@ -49,18 +49,19 @@
public async Task SubmitLoginLock() {
if (_account != null ) {
_account.SiteData.FailedPasswordLock = FailedLoginToggle;
_account.SiteData.PasswordAttempts = MaxFailedLogin;
_account.PasswordHash = "";
HttpResponseMessage SendVerifyEmail = await Http.PostAsJsonAsync("api/account/toggleAccountLock", _account);
LoginCounterResult = await SendVerifyEmail.Content.ReadAsStringAsync();
Dictionary<string, string> formData = new Dictionary<string, string>{
{ "UserName", _account.UserName },
{ "AccountLock", FailedLoginToggle.ToString() },
};
HttpResponseMessage Query = await Http.PostAsync("api/account/toggleAccountLock", new FormUrlEncodedContent(formData) );
LoginCounterResult = await Query.Content.ReadAsStringAsync();
}
}
protected override async Task OnInitializedAsync() {
HttpResponseMessage x = await Http.PostAsync("api/account/get", new StringContent(""));
string body = await x.Content.ReadAsStringAsync();
_account = JsonConvert.DeserializeObject<MistoxWebsite.Shared.Account>(body);
_account = JsonConvert.DeserializeObject<MistoxWebsite.Shared.Database.Account>(body);
if (_account != null){
FailedLoginToggle = _account.SiteData.FailedPasswordLock;
MaxFailedLogin = _account.SiteData.PasswordAttempts;
@@ -73,8 +74,11 @@
public async Task SendVerifyEmail() {
if (_account != null){
HttpResponseMessage SendVerifyEmail = await Http.PostAsJsonAsync("api/account/sendverifyemail", new MistoxWebsite.Shared.Account(){ UserName = _account.UserName });
bool result = await SendVerifyEmail.Content.ReadFromJsonAsync<bool>();
Dictionary<string, string> formData = new Dictionary<string, string>{
{ "UserName", _account.UserName },
};
HttpResponseMessage Query = await Http.PostAsync("api/account/sendverifyemail", new FormUrlEncodedContent(formData) );
bool result = await Query.Content.ReadFromJsonAsync<bool>();
if (result == true ) {
EmailSentResult = "Email Sent";
} else {
@@ -108,8 +112,13 @@
return;
}
if (_account != null){
HttpResponseMessage TryChangePassword = await Http.PostAsJsonAsync("api/account/changepassword", new MistoxWebsite.Shared.Account(){ UserName = _account.UserName, PasswordHash = CurPass, Error = NewPass1 });
bool resultText = await TryChangePassword.Content.ReadFromJsonAsync<bool>();
Dictionary<string, string> formData = new Dictionary<string, string>{
{ "UserName", _account.UserName },
{ "OldPassword", CurPass },
{ "NewPassword", NewPass1 }
};
HttpResponseMessage Query = await Http.PostAsync("api/account/changepassword", new FormUrlEncodedContent(formData) );
bool resultText = await Query.Content.ReadFromJsonAsync<bool>();
if (resultText == true ) {
PasswordErrorText = "Password changed successfully";
} else {
@@ -5,10 +5,6 @@
margin-bottom: 1.4rem;
}
.title-frame{
}
.title-frame h1 input{
padding-left: 1.4rem;
padding-top: 0.4rem;
@@ -1,6 +1,3 @@
body {
}
.lower-frame{
.lower-frame{
padding: 1.4rem;
}
@@ -119,12 +119,12 @@
}
async Task confirmDeleteAccount() {
HttpResponseMessage Delete = await Http.PostAsJsonAsync( "api/account/delete", new MistoxWebsite.Shared.Account(){
ID = Statics.User.ID,
UserName = Statics.User.Email,
PasswordHash = Password
});
string result = await Delete.Content.ReadAsStringAsync();
Dictionary<string, string> formData = new Dictionary<string, string>{
{ "UserName", Statics.User.UserName },
{ "Password", Password },
};
HttpResponseMessage Query = await Http.PostAsync("api/account/delete", new FormUrlEncodedContent(formData) );
string result = await Query.Content.ReadAsStringAsync();
bool status = result == "true" ? true : false;
if (status){
await Http.PostAsync("api/account/logout", new StringContent(""));
@@ -6,28 +6,11 @@
<div class="Big-Div">
<div id="DirTree">
@if (output != null ) {
<ExplorerChild Title=@output.Path Children=output.Children PartialPath="\"></ExplorerChild>
}
</div>
<span>@ErrorTxt</span>
</div>
@code{
public string ErrorTxt = "";
public DirObj? output = null;
protected override async void OnInitialized() {
try {
byte[] resultBody = await (await Http.PostAsync( "api/product/showdownloads", new StringContent("") )).Content.ReadAsByteArrayAsync();
string JsonData = Encoding.UTF8.GetString(resultBody);
output = JsonConvert.DeserializeObject<DirObj>( JsonData );
base.StateHasChanged();
} catch( Exception e ) {
ErrorTxt = "Error : " + e.ToString();
}
}
}
@@ -1,283 +0,0 @@
@page "/resume/derek"
<div class="PopOutFrame">
<div class="Content" style="height: 170px !important;">
<div class="ImgFrame">
<img class="Picture" src="/img/ResumeFace.jpg" />
</div>
<div class="NameFrame">
<h1>Derek Holloway</h1>
<h1>Owner and sole developer</h1>
</div>
<div class="ContactFrame">
<h1>derek@mistox.net</h1>
</div>
</div>
<div class="PopOutHr"></div>
</div>
<div class="PopOutFrame">
<div class="Content">
<h1 style="margin: 0; margin-bottom: 5px;">Work Experience</h1>
<!-- NAVWAR Assistant Contract Tech. Rep. -->
<div class="capsule" @onmouseenter="()=>{ MouseEnter(1); }" @onmouseleave="()=>{ MouseLeave(1); }">
<div class="Skills" style="height: calc(100% - 40px);">
<div class="paddedcell">
<h2 class="jobTitle">NAVWAR Assistant Contract Tech. Rep.</h2>
<h3 class="jobSub">Redhorse corp. - San Diego, CA</h3>
<h3 class="jobSub">888-445-8010</h3>
<h3 class="jobSub">February 2022 - Today</h3>
<span></span>
</div>
</div>
<div class="SkillsContent colored" style="height: calc(100% - 40px); @ContentStyle1">
<div class="paddedcell">
<ul>
<li><span>The first line of support for end users</span></li>
<li><span>Fix or escalate issues as required to the correct authority for resolution</span></li>
<li><span>The ACTR performs routine office IT functions managing mechanical and printer supplies</span></li>
<li><span>Assisting with connectivity to and troubleshooting networked systems and Video Teleconferences</span></li>
<li><span>This includes setting up new accounts</span></li>
<li><span>Managing users accesses</span></li>
<li><span>Uses the building badging system to grant access to appropriate personnel Assist with transition to Office 365 and Navy Flank Speed as required.</span></li>
<li><span>Leading role on Junior level tasks/projects</span></li>
<li><span>Supports the customer performing moderately complex tasks on a routine basis.</span></li>
<br />
<li><span>Project manager for NAVWAR tech refresh</span></li>
<li><span>Replacing 4010+ computers within a 1 year time-frame</span></li>
<li><span>Manage warranties with HP Federal</span></li>
<li><span>Coordinating orders and returns for old leased hardware</span></li>
</ul>
</div>
</div>
</div>
<!-- NMCI Field Service -->
<div class="capsule" @onmouseenter="()=>{ MouseEnter(2); }" @onmouseleave="()=>{ MouseLeave(2); }">
<div class="Skills" style="height: calc(100% - 40px);">
<div class="paddedcell">
<h2 class="jobTitle">NMCI Field Service Technitian</h2>
<h3 class="jobSub">Super Systems Inc - San Diego, CA</h3>
<h3 class="jobSub">757-399-3000 - info@supersystemsinc.com</h3>
<h3 class="jobSub">June 2021 - Feburary 2022</h3>
<br />
<h3 class="jobSub">Ohm Systems, Inc - San Diego, CA</h3>
<h3 class="jobSub">215-675-2766 - info@ohmsysinc.com</h3>
<h3 class="jobSub">February 2021 - June 2021</h3>
<span></span>
</div>
</div>
<div class="SkillsContent colored" style="height: calc(100% - 40px); @ContentStyle2">
<div class="paddedcell">
<ul>
<li><span>Performed layer 1 network troubleshooting; windows netsh firewalls, 802.1x Authentication issues, and cable and port issues.</span></li>
<li><span>Performed hardware troubleshooting and replacements; replacing laptop motherboards, displays, cpus, ram, and peripherals.</span></li>
<li><span>Performed software troubleshooting using event viewer, task manager, and command prompt. By uninstalling and reinstalling or reconfiguring.</span></li>
<li><span>Worked with network printers, voip's, and video telecommunication devices.</span></li>
<li><span>Worked face to face with customers, managing my time between calls and work orders.</span></li>
</ul>
</div>
</div>
</div>
<!-- NMCI Help Desk -->
<div class="capsule" @onmouseenter="()=>{ MouseEnter(3); }" @onmouseleave="()=>{ MouseLeave(3); }">
<div class="Skills" style="height: calc(100% - 40px);">
<div class="paddedcell">
<h2 class="jobTitle">NMCI Help Desk Technitian</h2>
<h3 class="jobSub">Apex Systems - Coronado, CA</h3>
<h3 class="jobSub">619-757-1646</h3>
<h3 class="jobSub">September 2019 - September 2020</h3>
<span></span>
</div>
</div>
<div class="SkillsContent colored" style="height: calc(100% - 40px); @ContentStyle3">
<div class="paddedcell">
<ul>
<li><span>Performed remote troubleshooting: windows cmd, winrs, rdc, winrs. Fixing software issues</span></li>
<li><span>Performed administrative Tasks: create active directory accounts and verifying identity to unlock accounts.</span></li>
<li><span>Walked users through diagnosing network issues over the phone or escalated issue to field services</span></li>
<li><span>Fixed users email issues; server mappings, proxy email addresses, shared emails, and outlook related issues.</span></li>
<li><span>Moved users profiles from one domain to another and moved users files along with it.</span></li>
<li><span>Fixed account related issues; id to user mismatch and wrong display name.</span></li>
</ul>
</div>
</div>
</div>
<!-- Warehouse Reciever -->
<div class="capsule" @onmouseenter="()=>{ MouseEnter(4); }" @onmouseleave="()=>{ MouseLeave(4); }">
<div class="Skills" style="height: calc(100% - 40px);">
<div class="paddedcell">
<h2 class="jobTitle">Warehouse receiver</h2>
<h3 class="jobSub">Ababa Bolt - El Cajon, CA</h3>
<h3 class="jobSub">619-440-1781</h3>
<h3 class="jobSub">May 2019 - August 2019</h3>
<span></span>
</div>
</div>
<div class="SkillsContent colored" style="height: calc(100% - 40px); @ContentStyle4">
<div class="paddedcell">
<ul>
<li><span>Verified that all parts came in off the packing slip</span></li>
<li><span>Rejected parts that were damaged and sent back to manufacturer</span></li>
<li><span>Sort and add parts into the tracking system</span></li>
<li><span>Put parts away in appropriate areas</span></li>
</ul>
</div>
</div>
</div>
<!-- Warehouse packer -->
<div class="capsule" @onmouseenter="()=>{ MouseEnter(5); }" @onmouseleave="()=>{ MouseLeave(5); }">
<div class="Skills" style="height: calc(100% - 40px);">
<div class="paddedcell">
<h2 class="jobTitle">Warehouse packer</h2>
<h3 class="jobSub">Ababa Bolt - El Cajon, CA</h3>
<h3 class="jobSub">619-440-1781</h3>
<h3 class="jobSub">October 2017 - September 2018</h3>
<span></span>
</div>
</div>
<div class="SkillsContent colored" style="height: calc(100% - 40px); @ContentStyle5">
<div class="paddedcell">
<ul>
<li><span>Find which parts need more stock on shelves</span></li>
<li><span>Split out parts by count or weight</span></li>
<li><span>Verified and marked appropriate compliance such as RoHS</span></li>
<li><span>Operated forklifts and scissor lifts</span></li>
</ul>
</div>
</div>
</div>
<!-- California Army National Guard -->
<div class="capsule" @onmouseenter="()=>{ MouseEnter(6); }" @onmouseleave="()=>{ MouseLeave(6); }">
<div class="Skills" style="height: calc(100% - 40px);">
<div class="paddedcell">
<h2 class="jobTitle">Motor Vehicle Trasport Operator</h2>
<h3 class="jobSub">California Army National Guard</h3>
<h3 class="jobSub">760-607-8574</h3>
<h3 class="jobSub">September 2018 - Today</h3>
<h3 class="jobSub">Rank/Grade - Specialist / E-4</h3>
<span></span>
</div>
</div>
<div class="SkillsContent colored" style="height: calc(100% - 40px); @ContentStyle6">
<div class="paddedcell">
<ul>
<li><span>88M - Motor Transport Operator</span></li>
<li><span>Neccesarry to hold secret clearence and keep all cyber security certifications up to date.</span></li>
<li><span>June 2020 - Protected and defended the Los Alamitos police department and Six Flags Magic Mountain during the rios cause by BLM movement that caused rioting in the streets.</span></li>
<li><span>September 2020 - Worked with Cal-Fire in Chico, CA and Alderpoint, CA to cut fire lines to prevent the spread of fires during the <a href="https://en.wikipedia.org/wiki/August_Complex_fire">August Fire Complex</a> fires.</span></li>
</ul>
</div>
</div>
</div>
</div>
<div class="PopOutHr"></div>
</div>
<div class="PopOutFrame" @onmouseenter="()=>{ MouseEnter(7); }" @onmouseleave="()=>{ MouseLeave(7); }">
<div class="Content">
<div class="Skills">
<h1>Development</h1>
<ul>
<li class="LIPrime">C#</li>
<li>Mono</li>
<li>ASP.NET</li>
<li>ASP Core</li>
<li>Blazor Web Assembly</li>
<li>Windows Forms Apps</li>
<li class="LIPrime">C++</li>
<li>Arm Embedded</li>
<li>Raspberry Pi</li>
<li class="LIPrime">Database</li>
<li>MySql</li>
<li>MsSql</li>
<li>LINQ</li>
<li class="LIPrime">Game Engines</li>
<li>Godot</li>
<li>Unity 3D</li>
<li>Solar 2D</li>
<li class="LIPrime">Web Development</li>
<li>Front End</li>
<li>Back End</li>
<li>Interfaces</li>
<li>Square Payment API</li>
<li>Rest Clients</li>
</ul>
</div>
<div class="SkillsContent" style="@ContentStyle7">
<div class="paddedcell textSection">
<a href="https://github.com/reverseslayer/LUADNS-DDNS">LUADNS-DDNS : https://github.com/reverseslayer/LUADNS-DDNS</a><br />
<span>This is a service that I made for </span><a href="http://luadns.com">luadns.com</a><span>. This allows free ddns by simply changing the dns name servers to luadns nameservers and running this program as a service. This was made for linux but shoud easily run on windows.</span><br /><br />
</div>
<div class="paddedcell textSection">
<a href="https://github.com/reverseslayer/MistoxServer">Mistox-Server : https://github.com/reverseslayer/MistoxServer</a><br />
<span>This is a </span><a href="https://en.wikipedia.org/wiki/UDP_hole_punching">UDP Hole Punched</a><span> server; that allows clients to direct connect over the wan without opening ports. It works by having a dedicated TCP server that routes the UDP connections directly to each client. Based on this </span><a href="img/IdeaMap.jpg">Idea map.</a>
</div>
<div class="paddedcell textSection">
<a href="https://www.mistox.net">Mistox.net : https://mistox.net</a><br />
<span>Mistox.net is all done by me. The DNS is hosted by <a href="https://domains.google.com">domains.google.com</a> and pushed through <a href="http://luadns.com">luadns.com</a> name server so that I can run LUA-DDNS a service I made to reach other places that behind ddns. The webservers are hosted by <a href="https://www.vultr.com/">vultr.com</a> and the entire stack is built on <a href="https://dotnet.microsoft.com/en-us/apps/aspnet">asp.net</a>. The payment services are run through <a href="https://stripe.com/">stripe-payments</a>. I built this as a side project but its slowly becoming more and more something that I would like to be able to share things that I make; paid or free.</span>
</div>
</div>
</div>
<div class="PopOutHr" style="margin-bottom: 30px;"></div>
</div>
@code {
string ContentStyle1 = "";
string ContentStyle2 = "";
string ContentStyle3 = "";
string ContentStyle4 = "";
string ContentStyle5 = "";
string ContentStyle6 = "";
string ContentStyle7 = "";
void MouseEnter( int frameNumber ) {
if (frameNumber == 1){
ContentStyle1 = "right: 0px;";
base.StateHasChanged();
}else if (frameNumber == 2){
ContentStyle2 = "right: 0px;";
base.StateHasChanged();
}else if (frameNumber == 3){
ContentStyle3 = "right: 0px;";
base.StateHasChanged();
}else if (frameNumber == 4){
ContentStyle4 = "right: 0px;";
base.StateHasChanged();
}else if (frameNumber == 5){
ContentStyle5 = "right: 0px;";
base.StateHasChanged();
}else if (frameNumber == 6){
ContentStyle6 = "right: 0px;";
base.StateHasChanged();
}else if (frameNumber == 7){
ContentStyle7 = "right: 0px;";
base.StateHasChanged();
}
}
void MouseLeave( int frameNumber ){
if (frameNumber == 1){
ContentStyle1 = "right: -700px;";
base.StateHasChanged();
}else if (frameNumber == 2){
ContentStyle2 = "right: -700px;";
base.StateHasChanged();
}else if (frameNumber == 3){
ContentStyle3 = "right: -700px;";
base.StateHasChanged();
}else if (frameNumber == 4){
ContentStyle4 = "right: -700px;";
base.StateHasChanged();
}else if (frameNumber == 5){
ContentStyle5 = "right: -700px;";
base.StateHasChanged();
}else if (frameNumber == 6){
ContentStyle6 = "right: -700px;";
base.StateHasChanged();
}else if (frameNumber == 7){
ContentStyle7 = "right: -700px;";
base.StateHasChanged();
}
}
}
@@ -1,191 +0,0 @@
* {
--popout-shadow-color-left: #8c8c8c;
--popout-shadow-color-bottom: #595959;
--popout-background-color: #004262;
--frame-background-color: #005662;
--frame-title-color: #ffffff;
--job-title-color: #f35100;
--job-sub-color: #c85c00;
--text-color: #dddddd;
--link-color: #4cff00;
--link-visited-color: #73ac5b;
--skills-bg-color: #c85c00;
--skills-text-color: #000;
--skills-text-shadow-color: #f35100;
--skills-prime-background-color: #972500;
--skills-prime-text-color: #fff;
}
body {
position: relative;
}
h1 {
color: var(--frame-title-color);
}
span {
color: var(--text-color);
}
.PopOutFrame {
position: relative;
background-color: white;
width: 100%;
max-width: 1080px;
margin: 15px auto 0 auto;
content: "";
}
.PopOutFrame::before {
position: absolute;
width: 6px;
left: -6px;
margin-top: 6px;
background: var(--popout-shadow-color-left);
content: "";
display: block;
transform: skew(0deg, -61deg);
height: 100%;
}
.PopOutHr {
width: 100%;
float: left;
}
.PopOutHr::after {
position: absolute;
width: 100%;
margin-top: 0px;
bottom: -11px;
left: -3px;
background: var(--popout-shadow-color-bottom);
content: "";
display: block;
transform: skew(-31deg, 0deg);
height: 11px;
}
.Content{
position: relative;
padding: 15px;
overflow: hidden;
background-color: var(--popout-background-color);
}
.ImgFrame {
float: left;
}
.Picture{
width: 140px;
height: 140px;
}
.NameFrame {
float: left;
width: calc(100% - 510px);
margin-left: 20px;
}
.ContactFrame {
float: left;
width: 300px;
height: 140px;
}
.ContactFrame h1{
font-size: 30px;
}
.SkillsContent {
position: relative;
float: left;
height: 100%;
width: 60%;
transition-duration: 2s;
right: -700px;
}
.SkillsContent :link {
color: var(--link-color);
}
.SkillsContent :visited{
color: var(--link-visited-color) !important;
}
.paddedcell {
padding: 10px 5px;
padding-bottom: 0;
margin-bottom: 5px;
}
.colored {
background-color: var(--frame-background-color);
}
.paddedcell br{
display: block;
margin: 10px 0;
content: "";
}
.Skills {
float: left;
height: 100%;
width: 40%;
transition-duration: 2s;
}
.Skills h1{
margin: 5px;
}
.Skills ul{
font-size: 14px;
list-style: none;
margin: 0;
padding: 0 5px;
}
.Skills li {
float: left;
padding: 4px 6px;
margin: 0 4px 4px 0;
background-color: var(--skills-bg-color);
text-shadow: 0 1px 1px var(--skills-text-shadow-color);
color: var(--skills-text-color);
}
.LIPrime{
text-shadow: none;
background-color: var(--skills-prime-background-color) !important;
color: var(--skills-prime-text-color) !important;
clear: left;
}
.capsule {
margin-top: 15px;
overflow: hidden;
border: solid var(--frame-background-color);
border-radius: 5px;
}
.jobTitle {
margin: 0;
color: var(--job-title-color);
}
.jobSub {
margin: 0;
color: var(--job-sub-color);
font-size: 15px;
}
.textSection {
margin-top: 15px;
background-color: var(--frame-background-color);
border-radius: 5px;
}
@@ -1,38 +0,0 @@
<button type="button" class="collapsible" @onclick=OpenCollapseable>@Title</button>
<ul class="dropdown-content" style="display : @collapseStyle;">
@if (Children != null){
@foreach(var Cur in Children){
<li>
@if(Cur.Type == FileType.Directory) {
<ExplorerChild Title=@Cur.Path Children=Cur.Children PartialPath=@(PartialPath+Cur.Path) ></ExplorerChild>
} else {
<button type="button" @onclick=@((e)=>{ Download(Cur.Path); })>@Cur.Path</button>
}
</li>
}
}
</ul>
@code{
[Parameter]
public string Title{ get; set; } = "";
[Parameter]
public DirObj[]? Children{ get; set; }
[Parameter]
public string PartialPath{ get; set; } = "";
public string collapseStyle = "none";
void OpenCollapseable() {
if (collapseStyle == "block") {
collapseStyle = "none";
} else {
collapseStyle = "block";
}
}
void Download(string Path) {
Nav.NavigateTo( "api/product/download?Product=" + PartialPath + Path, true );
}
}
@@ -7,7 +7,7 @@
@code {
protected override void OnInitialized() {
if (Statics.User.ID == -1 ) {
Nav.NavigateTo( "/account/login?ReturnURL=Null" );
Nav.NavigateTo( "/account/login" );
}
}
}
-164
View File
@@ -1,164 +0,0 @@
@page "/snake"
<div @onkeydown="OnKeyDown" tabindex="0" 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;">
<!-- Game -->
@foreach(SnakePart part in SnakeParts ) {
<div style="position: absolute; left: @part.getX(); top: @part.getY(); width: 10px; height: 10px; background-color: #111; border: 0; padding: 0; margin: 0;"></div>
}
<div style="position: absolute; left: @Collectable.getX(); top: @Collectable.getY(); width: 10px; height: 10px; background-color: #f00; border: 0; padding: 0; margin: 0;"></div>
<!-- End Game -->
</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>
</div>
@code {
struct SnakePart {
public int X{ get; set; }
public int Y{ get; set; }
public int Hue{ get; set; }
public string getX() {
return X * 10 + "px";
}
public string getY() {
return Y * 10 + "px";
}
}
enum Direction {
Up,
Down,
Left,
Right
}
List<SnakePart> SnakeParts = new List<SnakePart>(){
new SnakePart{ X = 5, Y = 10 }, // Tail
new SnakePart{ X = 6, Y = 10 },
new SnakePart{ X = 7, Y = 10 },
new SnakePart{ X = 8, Y = 10 } // Head
};
int Score = 0;
bool Paused = false;
Direction SnakeDirection = Direction.Right;
int FrameRate = 1000 / 10;
int HueRate = 5;
SnakePart Collectable = new SnakePart{ X = 15, Y = 15 };
void OnKeyDown(KeyboardEventArgs e) {
Console.WriteLine(e.Key);
if (e.Key.ToLower() == "w" ) {
SnakeDirection = Direction.Up;
}else if (e.Key.ToLower() == "a" ) {
SnakeDirection = Direction.Left;
}else if (e.Key.ToLower() == "s" ) {
SnakeDirection = Direction.Down;
}else if (e.Key.ToLower() == "d" ) {
SnakeDirection = Direction.Right;
}
}
bool CheckSelfHit() {
foreach(SnakePart cur in SnakeParts ) {
if (SnakeParts[SnakeParts.Count-1].X == cur.X ) {
if (SnakeParts[SnakeParts.Count-1].Y == cur.Y ) {
return false;
}
}
}
return true;
}
bool CheckBounds() {
if (SnakeParts[SnakeParts.Count-1].X > 0 && SnakeParts[SnakeParts.Count-1].X < 50 ) {
if (SnakeParts[SnakeParts.Count-1].Y > 0 && SnakeParts[SnakeParts.Count-1].Y < 50 ) {
return true;
}
}
return false;
}
bool CheckCollectibleHit() { // return true if hit
if (SnakeParts[SnakeParts.Count-1].X == Collectable.X ) {
if (SnakeParts[SnakeParts.Count-1].Y == Collectable.Y ) {
return true;
}
}
return false;
}
void ResetCollectable() {
Collectable.X = new Random().Next(1, 40);
Collectable.Y = new Random().Next(1, 40);
}
void Die() {
}
void Update() {
// Get Next Position
if( SnakeDirection == Direction.Up ) {
SnakeParts.Add( new SnakePart {
X = SnakeParts[SnakeParts.Count-1].X,
Y = SnakeParts[SnakeParts.Count-1].Y - 1,
Hue = SnakeParts[SnakeParts.Count-1].Hue + HueRate
});
}else if (SnakeDirection == Direction.Right ) {
SnakeParts.Add( new SnakePart {
X = SnakeParts[SnakeParts.Count-1].X + 1,
Y = SnakeParts[SnakeParts.Count-1].Y,
Hue = SnakeParts[SnakeParts.Count-1].Hue + HueRate
});
}else if (SnakeDirection == Direction.Down ) {
SnakeParts.Add( new SnakePart {
X = SnakeParts[SnakeParts.Count-1].X,
Y = SnakeParts[SnakeParts.Count-1].Y + 1,
Hue = SnakeParts[SnakeParts.Count-1].Hue + HueRate
});
}else if (SnakeDirection == Direction.Left ) {
SnakeParts.Add( new SnakePart {
X = SnakeParts[SnakeParts.Count-1].X - 1,
Y = SnakeParts[SnakeParts.Count-1].Y,
Hue = SnakeParts[SnakeParts.Count-1].Hue + HueRate
});
}
if (CheckSelfHit() && CheckBounds() ) {
if( CheckCollectibleHit() ) {
Score += 1;
ResetCollectable();
} else {
SnakeParts.RemoveAt( 0 );
}
} else {
Die();
}
StateHasChanged();
}
protected override void OnInitialized() {
ResetCollectable();
var timer = new System.Threading.Timer((e) => {
if (!Paused){
Update();
}
}, null, 0, FrameRate );
}
}
@@ -4,7 +4,7 @@
<h3 class="cart-title">Cart</h3>
<div class="Spacer">
@foreach( MistoxWebsite.Shared.Cart obj in Statics.Carts ) {
@foreach( MistoxWebsite.Shared.Database.Cart obj in Statics.Carts ) {
<div class="cart-item">
<h1>@getItem(obj.ProductID)?.Name</h1>
@foreach( string cur in getItem( obj.ProductID )?.Images ) {
@@ -43,7 +43,7 @@
protected override void OnInitialized() {
total = 0;
foreach( MistoxWebsite.Shared.Cart obj in Statics.Carts ) {
foreach( MistoxWebsite.Shared.Database.Cart obj in Statics.Carts ) {
foreach( Product item in Statics.Products ) {
if( obj.ProductID == item.ID ) {
total = total + (item.Cost / 100f);
@@ -99,7 +99,7 @@
public bool isOwned(int ID ) {
if(Statics.Owned.Count > 0 ) {
foreach( MistoxWebsite.Shared.Receipt cur in Statics.Owned ) {
foreach( MistoxWebsite.Shared.Database.Receipt cur in Statics.Owned ) {
if( cur.ProductID == ID ) {
return true;
}
@@ -109,7 +109,7 @@
}
public bool isInCart(int id) {
foreach( MistoxWebsite.Shared.Cart cur in Statics.Carts ) {
foreach( MistoxWebsite.Shared.Database.Cart cur in Statics.Carts ) {
if (cur.ProductID == id ) {
return true;
}
@@ -118,7 +118,7 @@
}
public async void onAddToCart( int ID ) {
MistoxWebsite.Shared.Cart item = new MistoxWebsite.Shared.Cart {
MistoxWebsite.Shared.Database.Cart item = new MistoxWebsite.Shared.Database.Cart {
ProductID = ID,
AccountID = Statics.User.ID
};
@@ -1,6 +1,6 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;
using MistoxWebsite.Shared;
using MistoxWebsite.Shared.DTO.Session;
using Newtonsoft.Json;
namespace MistoxWebsite.Client.AuthState {
+1 -1
View File
@@ -1,4 +1,4 @@
using MistoxWebsite.Shared;
using MistoxWebsite.Shared.Database;
namespace MistoxWebsite.Client.Statics {
public class Statics {
+13 -9
View File
@@ -1,24 +1,28 @@
@using System.Net.Http
@using System.Net.Http.Json
@using System.Net.Mail
@using System.Security.Claims
@using System.Security.Cryptography
@using System.Text
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using MistoxWebsite.Client
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using System.Security.Claims
@using MistoxWebsite.Client
@using MistoxWebsite.Client.AuthState
@using MistoxWebsite.Client.Statics
@using System.Security.Cryptography
@using System.Text
@using MistoxWebsite.Shared
@using Newtonsoft.Json
@using MistoxWebsite.Client.Pages.Shared
@using MistoxWebsite.Shared.Database
@using MistoxWebsite.Shared.DTO.Account
@using MistoxWebsite.Shared.DTO.Session
@using Newtonsoft.Json
@inject IJSRuntime JS
@inject NavigationManager Nav
@@ -1,10 +1,11 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
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;
using MistoxWebsite.Shared.Database;
using MistoxWebsite.Shared.DTO.Session;
namespace MistoxWebsite.Server.Controllers {
[ApiController]
@@ -12,29 +13,27 @@ namespace MistoxWebsite.Server.Controllers {
DatabaseService _accountContext;
EmailService _emailContext;
public AuthenticationController( DatabaseService DatabaseContext, EmailService emailContext ) {
public AuthenticationController(DatabaseService DatabaseContext, EmailService emailContext) {
_accountContext = DatabaseContext;
_emailContext = emailContext;
}
// In Account -> References UserName / PasswordHash
// Out Account
[Route( "api/account/login" )]
[Route("api/account/login")]
[HttpPost]
public async Task<ActionResult<Account>> Login( [FromBody] Account request ) {
public async Task<ActionResult<Account>> Login([FromForm] string UserName, [FromForm] string PasswordHash, [FromForm] bool StayLoggedIn) {
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 ) {
Account? test = await _accountContext.GetAccount(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 ) ) {
if (BCrypt.Net.BCrypt.Verify(PasswordHash, test.PasswordHash)) {
test.SiteData.CurrentPasswordAttempts = 0;
await _accountContext.SetAccount( test );
await _accountContext.SetAccount(test);
AccountClaims aClaims = await getClaims(test.ID);
List<Claim> claims = new List<Claim>() {
@@ -48,64 +47,306 @@ namespace MistoxWebsite.Server.Controllers {
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal( new ClaimsIdentity( claims, "Auth" ) ),
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
IsPersistent = StayLoggedIn, // Is set from the StayLoggedIn
}
);
return test;
} else {
}
else {
test.SiteData.CurrentPasswordAttempts += 1;
await _accountContext.SetAccount( test );
await _accountContext.SetAccount(test);
return new Account() { Error = "Wrong password" };
}
}else{
await SendVerify(test);
}
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 ) {
} catch (Exception ex) {
return new Account() { Error = ex.Message };
}
}
// In Account -> References UserName / PasswordHash
// Out Account
[Route( "api/account/session" )]
[Route("api/account/session")]
[HttpPost]
public async Task<ActionResult<Account>> LoginSession( [FromBody] Account request ) {
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 ) {
if (test != null) {
if (request.PasswordHash == test.PasswordHash) {
return test;
} else {
}
else {
test.SiteData.CurrentPasswordAttempts += 1;
await _accountContext.SetAccount( test );
await _accountContext.SetAccount(test);
return new Account() { Error = "Wrong password" };
}
}
return new Account() { Error = "User doesn't exist" };
} catch( Exception ex ) {
} catch (Exception ex) {
return new Account() { Error = ex.Message };
}
}
// In Account
// Out List<String>
[Route( "api/account/claims" )]
[Route("api/account/claims")]
[HttpPost]
public async Task<ActionResult<AccountClaims>> Claims( [FromBody] Account Account ) {
public async Task<ActionResult<AccountClaims>> Claims([FromBody] Account Account) {
AccountClaims claims = await getClaims(Account.ID);
return claims;
}
async Task<AccountClaims> getClaims( int AccountID ) {
[Route("api/account/register")]
[HttpPost]
public async Task<ActionResult<Account>> Register([FromForm] string Email, [FromForm] string UserName, [FromForm] string PasswordHash) {
try {
if (await _accountContext.GetAccount(UserName.ToLower()) == null) {
if (await _accountContext.GetAccount(Email.ToLower()) == null) {
Account? created = new Account() {
UserName = UserName.ToLower(),
Email = Email.ToLower(),
EmailVerified = false,
PasswordHash = BCrypt.Net.BCrypt.HashPassword(PasswordHash),
};
await _accountContext.NewAccount(created);
created = await _accountContext.GetAccount(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.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("api/account/changepassword")]
[HttpPost]
public async Task<ActionResult<bool>> ChangePassword([FromForm]string UserName, [FromForm]string OldPassword, [FromForm]string NewPassword) {
try {
Account? test = await _accountContext.GetAccount(UserName.ToLower());
if (test != null) {
if (BCrypt.Net.BCrypt.Verify(OldPassword, test.PasswordHash)) {
test.PasswordHash = BCrypt.Net.BCrypt.HashPassword(NewPassword);
test.SiteData.CurrentPasswordAttempts = 0;
await _accountContext.SetAccount(test);
return true;
}
}
return false;
} catch {
return false;
}
}
[Route("api/account/toggleAccountLock")]
[HttpPost]
public async Task<ActionResult<string>> ToggleAccountLock([FromForm]string UserName, [FromForm]bool AccountLock) {
try {
Account? test = await _accountContext.GetAccount(UserName);
if (test != null) {
test.SiteData.FailedPasswordLock = AccountLock;
test.SiteData.CurrentPasswordAttempts = 0;
await _accountContext.SetAccount(test);
return "Account Lock Status Updated";
}
return "Unknown Error Occurred";
} catch (Exception ex) {
return ex.Message;
}
}
[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();
}
}
[Route("api/account/logout")]
[HttpPost]
public async Task Logout() {
await HttpContext.SignOutAsync();
}
[Route("api/account/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 _accountContext.GetAccount(UserName.ToLower());
if (test != null) {
test.SiteData.EmailToken = Guid.NewGuid().ToString();
await _accountContext.SetAccount(test);
string EmailContents = EmailService.VerifyEmailEmail;
EmailContents = Substitue(EmailContents, "@UserName", UserName);
EmailContents = Substitue(EmailContents, "@UserName", 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";
}
}
[Route("api/account/verifyemail")]
[HttpPost]
public async Task<ActionResult<bool>> VerifyEmail([FromForm]string UserName, [FromForm]string EmailToken) {
try {
Account? test = await _accountContext.GetAccount(UserName.ToLower());
if (test != null) {
if (test.SiteData.EmailToken == EmailToken) {
test.SiteData.EmailToken = "";
test.EmailVerified = true;
await _accountContext.SetAccount(test);
return true;
}
}
return false;
} catch {
return false;
}
}
[Route("api/account/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 _accountContext.GetAccount(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";
}
}
[Route("api/account/resetpassword")]
[HttpPost]
public async Task<ActionResult<bool>> ResetPwdVerify([FromForm] string UserName, [FromForm] string NewPassword, [FromForm] string ResetToken) {
try {
Account? test = await _accountContext.GetAccount(UserName.ToLower());
if (test != null && !string.IsNullOrEmpty(test.SiteData.EmailToken)) {
if (test.SiteData.EmailToken == ResetToken) {
test.SiteData.CurrentPasswordAttempts = 0;
test.PasswordHash = BCrypt.Net.BCrypt.HashPassword(NewPassword);
await _accountContext.SetAccount(test);
return true;
}
}
return false;
} catch {
return false;
}
}
[Route("api/account/delete")]
[HttpPost]
public async Task<ActionResult<bool>> delete([FromForm]string UserName, [FromForm]string Password) {
try {
Account? test = await _accountContext.GetAccount(UserName.ToLower());
if (test != null) {
if (BCrypt.Net.BCrypt.Verify(Password, test.PasswordHash)) {
await _accountContext.DeleteAccount(test);
return true;
}
}
return false;
} catch {
return false;
}
}
// Helper Functions
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;
}
async Task<AccountClaims> getClaims(int AccountID) {
try {
Account? test = await _accountContext.GetAccountByID(AccountID);
if( test != null ) {
if (test != null) {
AccountClaims aClaims = new AccountClaims() {
UserName = test.UserName,
Email = test.Email,
@@ -121,265 +362,5 @@ namespace MistoxWebsite.Server.Controllers {
}
}
// 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;
}
}
}
}
@@ -1,6 +1,6 @@
using MistoxWebsite.Server.Services.DatabaseService;
using System.Security.Claims;
using MistoxWebsite.Shared;
using MistoxWebsite.Shared.DTO.Session;
using Microsoft.AspNetCore.Mvc;
namespace MistoxWebsite.Server.Controllers {
@@ -1,12 +1,8 @@
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc;
using MistoxWebsite.Server.Controllers.Payment;
using MistoxWebsite.Server.Services.DatabaseService;
using MistoxWebsite.Shared;
using Newtonsoft.Json;
using MistoxWebsite.Shared.Database;
using Stripe;
using Stripe.Climate;
using Stripe.Tax;
namespace MistoxWebsite.Server.Controllers {
[ApiController]
@@ -24,7 +20,7 @@ namespace MistoxWebsite.Server.Controllers {
public async Task<string> GetPaymentKey( [FromQuery] string userID ) {
string OrderNumber = Guid.NewGuid().ToString().Substring(0,10);
Shared.Account? acc = await _databaseService.GetAccount(userID);
Shared.Database.Account? acc = await _databaseService.GetAccount(userID);
if (acc != null) {
List<Cart> cart = await _databaseService.GetCart(acc);
@@ -84,7 +80,7 @@ namespace MistoxWebsite.Server.Controllers {
}
// Clear the cart
Shared.Account account = new Shared.Account{
Shared.Database.Account account = new() {
ID = userID
};
await _databaseService.ClearCart( account );
@@ -1,4 +1,4 @@
using MistoxWebsite.Shared;
using MistoxWebsite.Shared.Database;
namespace MistoxWebsite.Server.Controllers.Payment {
@@ -1,9 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using MistoxWebsite.Server.Controllers.Payment;
using MistoxWebsite.Server.Services.DatabaseService;
using MistoxWebsite.Shared;
using MistoxWebsite.Shared.Database;
using Stripe;
using Stripe.Tax;
@@ -17,7 +14,7 @@ namespace MistoxWebsite.Server.Controllers {
_databaseService = databaseService;
}
public async Task<(bool, string)> Purchase(string OrderNumber, Shared.Account user, List<Cart> cart) {
public async Task<(bool, string)> Purchase(string OrderNumber, Shared.Database.Account user, List<Cart> cart) {
try {
// build Recipt and calculate Tax
var options = new CalculationCreateOptions {
@@ -34,7 +31,7 @@ namespace MistoxWebsite.Server.Controllers {
// Add items to receipt
int subtotal = 0;
foreach (Cart items in cart) {
Shared.Product? product = await _databaseService.GetProduct(items.ProductID);
Shared.Database.Product? product = await _databaseService.GetProduct(items.ProductID);
if (product != null) {
prods.Add(product.ID);
if (product != null) {
@@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using MistoxWebsite.Server.Services.DatabaseService;
using MistoxWebsite.Shared;
using MistoxWebsite.Shared.Database;
using Newtonsoft.Json;
using System.Security.Claims;
using System.Text;
@@ -128,74 +128,6 @@ namespace MistoxWebsite.Server.Controllers {
}
}
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++ ) {
@@ -221,10 +153,10 @@ namespace MistoxWebsite.Server.Controllers {
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
};
//FileStream fileStream = new FileStream(_FolderRoot + Product, FileMode.Open, FileAccess.Read);
//return new FileStreamResult( fileStream, "application/octet-stream" ) {
// FileDownloadName = fileStream.Name
//};
}
break;
}
@@ -1,19 +0,0 @@
{
"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
}
}
}
@@ -1,4 +1,4 @@
using MistoxWebsite.Shared;
using MistoxWebsite.Shared.Database;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
@@ -1,4 +1,5 @@
using MistoxWebsite.Shared;
using MistoxWebsite.Shared.Database;
using MistoxWebsite.Shared.DTO.Account;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
@@ -1,4 +1,4 @@
using MistoxWebsite.Shared;
using MistoxWebsite.Shared.Database;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
@@ -1,6 +1,6 @@
using MistoxWebsite.Shared;
using MistoxWebsite.Shared.Database;
using MistoxWebsite.Shared.DTO.Session;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
namespace MistoxWebsite.Server.Services.DatabaseService {
@@ -1,4 +1,4 @@
using MistoxWebsite.Shared;
using MistoxWebsite.Shared.Database;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
@@ -1,4 +1,4 @@
using MistoxWebsite.Shared;
using MistoxWebsite.Shared.Database;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
@@ -1,4 +1,4 @@
using MistoxWebsite.Shared;
using MistoxWebsite.Shared.Database;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
@@ -46,8 +46,8 @@ namespace MistoxWebsite.Server.Services.DatabaseService {
return receipts;
}
public async Task<List<ReceiptProduct>> GetAllReceiptsJoinedToProduct( Account account ) {
List<ReceiptProduct> join = new List<ReceiptProduct> ();
public async Task<List<( Receipt, Product )>> GetAllReceiptsJoinedToProduct( Account account ) {
List<( Receipt, Product )> join = new();
using( MySqlConnection connection = GetConnection() ) {
connection.Open();
string command = @"
@@ -78,24 +78,25 @@ namespace MistoxWebsite.Server.Services.DatabaseService {
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
}
} );
Receipt r = new() {
AccountID = _accountid,
ProductID = _gameid,
ReceiptID = _receiptid,
Time = _receiptdate,
TotalCost = _totalcost,
TaxAmount = _taxamount,
LineItem = _lineitem
};
Product p = new() {
ID = _id,
Cost = _cost,
Description = _desc,
Name = _name,
URL = _url
};
join.Add( (r, p) );
}
}
}
@@ -1,4 +1,4 @@
using MistoxWebsite.Shared;
using MistoxWebsite.Shared.Database;
using MySql.Data.MySqlClient;
using System.Data;
using System.Data.Common;
@@ -1,5 +1,3 @@
using System.Net.Mail;
namespace MistoxWebsite.Server.Services {
public partial class EmailService {
@@ -1,5 +1,3 @@
using System.Net.Mail;
namespace MistoxWebsite.Server.Services {
public partial class EmailService {
@@ -11,6 +11,7 @@
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
background-color: --var(--Mistox-Black);
}
main {
@@ -0,0 +1,20 @@
namespace MistoxWebsite.Shared.DTO.Account {
public class UserInventory {
public string Item { get; set; } = string.Empty;
public int Quantity { get; set; }
public string Stats { get; set; } = string.Empty;
}
public class PaymentObject {
public string CardNumber { get; set; } = string.Empty;
public long ExperationMonth { get; set; }
public long ExperationYear { get; set; }
public string CVC { get; set; } = string.Empty;
public string FullName { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string Zip { get; set; } = string.Empty;
public List<int> productIDs { get; set; } = new List<int>();
}
}
@@ -0,0 +1,21 @@
using MistoxWebsite.Shared.Database;
namespace MistoxWebsite.Shared.DTO.Session {
public class PageLoadObject {
public Database.Account? user { get; set; }
public AccountClaims? claims { get; set; }
public List<Receipt>? receipts { get; set; }
public List<Product>? products { get; set; }
public List<Cart>? Cart { get; set; }
}
public class AccountClaims {
public string UserName { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string EmailVerified { get; set; } = string.Empty;
public string Role { get; set; } = string.Empty;
public string FailedPasswordLock { get; set; } = string.Empty;
}
}
+25 -76
View File
@@ -1,27 +1,6 @@
using System.Diagnostics;
// Reflections of SQL Database objects
// Reflections of SQL Database objects
namespace MistoxWebsite.Shared {
public class PageLoadObject {
public Account? user { get; set; }
public AccountClaims? claims { get; set; }
public List<Receipt>? receipts { get; set; }
public List<Product>? products { get; set; }
public List<Cart>? Cart { get; set; }
}
public class DirObj {
public FileType? Type { get; set; }
public string Path { get; set; } = "";
public DirObj? [] Children { get; set; } = new DirObj?[0];
}
public enum FileType {
File,
Directory
}
namespace MistoxWebsite.Shared.Database {
public class Account {
public int ID { get; set; } // PK
@@ -33,25 +12,6 @@ namespace MistoxWebsite.Shared {
public string Error { get; set; } = "";
}
public class Product {
public int ID { get; set; } // PK
public string Name { get; set; } = "";
public string Description { get; set; } = "";
public int CurShowingIMG = 0;
public List<string> Images { get; set; } = new List<string>();
public int Cost { get; set; }
public string URL { get; set; } = "";
}
public class WebSiteData {
public int AccountID { get; set; } // PK
public bool FailedPasswordLock { get; set; } = false;
public int PasswordAttempts { get; set; } = 5;
public int CurrentPasswordAttempts { get; set; } = 0;
public string Role { get; set; } = "Generic";
public string EmailToken { get; set; } = "";
}
public class AccountInventory {
public int AccountID { get; set; } // PK
public int ProductID { get; set; } // PK
@@ -60,25 +20,14 @@ namespace MistoxWebsite.Shared {
public string Stats { get; set; } = string.Empty;
}
public class UserInventory {
public string Item { get; set; } = string.Empty;
public int Quantity { get; set; }
public string Stats { get; set; } = string.Empty;
}
public class Receipt {
public int AccountID { get; set; } // PK
public int ProductID { get; set; } // PK
public string ReceiptID { get; set; } = string.Empty;
public int LineItem { get; set; }
public int TaxAmount { get; set; }
public int TotalCost { get; set; }
public DateTime Time { get; set; }
}
public class ReceiptProduct {
public Receipt receipt { get; set; } = new Receipt();
public Product product { get; set; } = new Product();
public class Product {
public int ID { get; set; } // PK
public string Name { get; set; } = "";
public string Description { get; set; } = "";
public int CurShowingIMG = 0;
public List<string> Images { get; set; } = new List<string>();
public int Cost { get; set; }
public string URL { get; set; } = "";
}
public class Cart {
@@ -97,23 +46,23 @@ namespace MistoxWebsite.Shared {
public int Deaths { get; set; }
}
public class AccountClaims {
public string UserName { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string EmailVerified { get; set; } = string.Empty;
public string Role { get; set; } = string.Empty;
public string FailedPasswordLock { get; set; } = string.Empty;
public class Receipt {
public int AccountID { get; set; } // PK
public int ProductID { get; set; } // PK
public string ReceiptID { get; set; } = string.Empty;
public int LineItem { get; set; }
public int TaxAmount { get; set; }
public int TotalCost { get; set; }
public DateTime Time { get; set; }
}
public class PaymentObject {
public string CardNumber { get; set; } = string.Empty;
public long ExperationMonth { get; set; }
public long ExperationYear { get; set; }
public string CVC { get; set; } = string.Empty;
public string FullName { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string Zip { get; set; } = string.Empty;
public List<int> productIDs { get; set; } = new List<int>();
public class WebSiteData {
public int AccountID { get; set; } // PK
public bool FailedPasswordLock { get; set; } = false;
public int PasswordAttempts { get; set; } = 5;
public int CurrentPasswordAttempts { get; set; } = 0;
public string Role { get; set; } = "Generic";
public string EmailToken { get; set; } = "";
}
}