diff --git a/backendCs.Tests/.vscode/launch.json b/backendCs.Tests/.vscode/launch.json new file mode 100644 index 0000000..e395607 --- /dev/null +++ b/backendCs.Tests/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/bin/Debug/net8.0/backendCs.Test.dll", + "args": [], + "cwd": "${workspaceFolder}", + // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/backendCs.Tests/.vscode/tasks.json b/backendCs.Tests/.vscode/tasks.json new file mode 100644 index 0000000..10f826c --- /dev/null +++ b/backendCs.Tests/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/backendCs.Test.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/backendCs.Test.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary;ForceNoAlign" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/backendCs.Test.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/backendCs.Tests/UnitTest1.cs b/backendCs.Tests/UnitTest1.cs index d6389eb..b76bd10 100644 --- a/backendCs.Tests/UnitTest1.cs +++ b/backendCs.Tests/UnitTest1.cs @@ -1,11 +1,13 @@ namespace backendCs.Test; + using System.Net.Http; +using System.Text; [TestClass] public class UnitTest1 { [TestMethod] - async public Task TestMethodReset() + public async Task TestMethodReset() { using (HttpClient client = new HttpClient()) { @@ -16,122 +18,193 @@ public class UnitTest1 Assert.AreEqual((int)response.StatusCode, 200); } } + [TestMethod] - async public Task TestMethodGetall1() + public async Task TestMethodGetall1() { using (HttpClient client = new HttpClient()) { // Make a GET request to a URL - HttpResponseMessage response = await client.GetAsync("http://localhost:5000/api/getall?offset=10"); + HttpResponseMessage response = await client.GetAsync( + "http://localhost:5000/api/getall?offset=10" + ); // Ensure we have a successful response Assert.AreEqual((int)response.StatusCode, 200); } } + [TestMethod] - async public Task TestMethodGetall2() + public async Task TestMethodGetall2() { using (HttpClient client = new HttpClient()) { // Make a GET request to a URL - HttpResponseMessage response = await client.GetAsync("http://localhost:5000/api/getall?offset="); + HttpResponseMessage response = await client.GetAsync( + "http://localhost:5000/api/getall?offset=" + ); // Ensure we have a successful response Assert.AreEqual((int)response.StatusCode, 400); } } - async public Task TestMethodGetall3() + + [TestMethod] + public async Task TestMethodGetall3() { using (HttpClient client = new HttpClient()) { // Make a GET request to a URL - HttpResponseMessage response = await client.GetAsync("http://localhost:5000/api/getall?offset=10&from=2020-01-01&to=2024-01-01&orderby=time&order=true"); + HttpResponseMessage response = await client.GetAsync( + "http://localhost:5000/api/getall?offset=10&from=2020-01-01&to=2024-01-01&orderby=time&order=true" + ); // Ensure we have a successful response Assert.AreEqual((int)response.StatusCode, 200); } } + [TestMethod] - async public Task TestMethodGettopten1() + public async Task TestMethodGettopten1() { using (HttpClient client = new HttpClient()) { // Make a GET request to a URL - HttpResponseMessage response = await client.GetAsync("http://localhost:5000/api/gettopten?from=2000-01-01&to=2024-01-01&filterby=project"); + HttpResponseMessage response = await client.GetAsync( + "http://localhost:5000/api/gettopten?from=2000-01-01&to=2024-01-01&filterby=project" + ); // Ensure we have a successful response Assert.AreEqual((int)response.StatusCode, 200); } } + [TestMethod] - async public Task TestMethodGettopten2() + public async Task TestMethodGettopten2() { using (HttpClient client = new HttpClient()) { // Make a GET request to a URL - HttpResponseMessage response = await client.GetAsync("http://localhost:5000/api/gettopten?from=2000-01-01&to=2024-01-01&filterby=user"); + HttpResponseMessage response = await client.GetAsync( + "http://localhost:5000/api/gettopten?from=2000-01-01&to=2024-01-01&filterby=user" + ); // Ensure we have a successful response Assert.AreEqual((int)response.StatusCode, 200); } } + [TestMethod] - async public Task TestMethodGettopten3() + public async Task TestMethodGettopten3() { using (HttpClient client = new HttpClient()) { // Make a GET request to a URL - HttpResponseMessage response = await client.GetAsync("http://localhost:5000/api/gettopten?to=2024-01-01&filterby=project"); + HttpResponseMessage response = await client.GetAsync( + "http://localhost:5000/api/gettopten?to=2024-01-01&filterby=project" + ); // Ensure we have a successful response Assert.AreEqual((int)response.StatusCode, 400); } } + [TestMethod] - async public Task TestMethodGettopten4() + public async Task TestMethodGettopten4() { using (HttpClient client = new HttpClient()) { // Make a GET request to a URL - HttpResponseMessage response = await client.GetAsync("http://localhost:5000/api/gettopten?from=2000-01-01&filterby=project"); + HttpResponseMessage response = await client.GetAsync( + "http://localhost:5000/api/gettopten?from=2000-01-01&filterby=project" + ); // Ensure we have a successful response Assert.AreEqual((int)response.StatusCode, 400); } } + [TestMethod] - async public Task TestMethodGettopten5() + public async Task TestMethodGettopten5() { using (HttpClient client = new HttpClient()) { // Make a GET request to a URL - HttpResponseMessage response = await client.GetAsync("http://localhost:5000/api/gettopten?from=2000-01-01&to=2024-01-01"); + HttpResponseMessage response = await client.GetAsync( + "http://localhost:5000/api/gettopten?from=2000-01-01&to=2024-01-01" + ); // Ensure we have a successful response Assert.AreEqual((int)response.StatusCode, 400); } } + [TestMethod] - async public Task TestMethodGetuser1() + public async Task TestMethodGetuser1() { using (HttpClient client = new HttpClient()) { // Make a GET request to a URL - HttpResponseMessage response = await client.GetAsync("http://localhost:5000/api/getuser?userid=1"); + HttpResponseMessage response = await client.GetAsync( + "http://localhost:5000/api/getuser?userid=1" + ); // Ensure we have a successful response Assert.AreEqual((int)response.StatusCode, 200); } } - async public Task TestMethodGetuser2() + + [TestMethod] + public async Task TestMethodGetuser2() { using (HttpClient client = new HttpClient()) { // Make a GET request to a URL - HttpResponseMessage response = await client.GetAsync("http://localhost:5000/api/getuser"); + HttpResponseMessage response = await client.GetAsync( + "http://localhost:5000/api/getuser" + ); // Ensure we have a successful response Assert.AreEqual((int)response.StatusCode, 400); } } + + [TestMethod] + public async Task TestMethodRegister1() + { + using (HttpClient client = new()) + { + // Make a GET request to a URL + var jsonData = + "{ \"f_name\": \"donna\", \"l_name\": \"cow\", \"mail\": \"tombo@mail.com\", \"password\": \"1234567890\" }"; + var content = new StringContent(jsonData, Encoding.UTF8, "application/json"); + + HttpResponseMessage response = await client.PostAsync( + "http://localhost:5000/api/register", + content + ); + + // Ensure we have a successful response + Assert.AreEqual((int)response.StatusCode, 200); + } + } + + [TestMethod] + public async Task TestMethodLogin() + { + using (HttpClient client = new()) + { + // Make a GET request to a URL + var jsonData = "{ \"mail\": \"tombo@mail.com\", \"password\": \"1234567890\" }"; + var content = new StringContent(jsonData, Encoding.UTF8, "application/json"); + + HttpResponseMessage response = await client.PostAsync( + "http://localhost:5000/api/login", + content + ); + + // Ensure we have a successful response + Assert.AreEqual((int)response.StatusCode, 200); + } + } } diff --git a/backendCs.Tests/bin/Debug/net8.0/backendCs.Test.dll b/backendCs.Tests/bin/Debug/net8.0/backendCs.Test.dll index 2ef8f6b..902e9a3 100644 Binary files a/backendCs.Tests/bin/Debug/net8.0/backendCs.Test.dll and b/backendCs.Tests/bin/Debug/net8.0/backendCs.Test.dll differ diff --git a/backendCs.Tests/bin/Debug/net8.0/backendCs.Test.pdb b/backendCs.Tests/bin/Debug/net8.0/backendCs.Test.pdb index 5fbc81e..857d400 100644 Binary files a/backendCs.Tests/bin/Debug/net8.0/backendCs.Test.pdb and b/backendCs.Tests/bin/Debug/net8.0/backendCs.Test.pdb differ diff --git a/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.AssemblyInfo.cs b/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.AssemblyInfo.cs index 58ec18b..1f56ec4 100644 --- a/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.AssemblyInfo.cs +++ b/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("backendCs.Test")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+8e4317abde8c48644e2bc317481f0f846c577d4b")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+cb7b3ad94c91aad561fa90871a3e078e741f566c")] [assembly: System.Reflection.AssemblyProductAttribute("backendCs.Test")] [assembly: System.Reflection.AssemblyTitleAttribute("backendCs.Test")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.AssemblyInfoInputs.cache b/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.AssemblyInfoInputs.cache index 741f731..434311b 100644 --- a/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.AssemblyInfoInputs.cache +++ b/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.AssemblyInfoInputs.cache @@ -1 +1 @@ -a3618e90ec8e0b41c39e691b17b268fc26531e93f58c71336bc37fefe3594fc9 +d5818043832e259ded45b9771c78c909a325898a23799ca0c691beda0cd33197 diff --git a/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.dll b/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.dll index 2ef8f6b..902e9a3 100644 Binary files a/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.dll and b/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.dll differ diff --git a/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.pdb b/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.pdb index 5fbc81e..857d400 100644 Binary files a/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.pdb and b/backendCs.Tests/obj/Debug/net8.0/backendCs.Test.pdb differ diff --git a/backendCs.Tests/obj/Debug/net8.0/ref/backendCs.Test.dll b/backendCs.Tests/obj/Debug/net8.0/ref/backendCs.Test.dll index 49bd1db..4bb4000 100644 Binary files a/backendCs.Tests/obj/Debug/net8.0/ref/backendCs.Test.dll and b/backendCs.Tests/obj/Debug/net8.0/ref/backendCs.Test.dll differ diff --git a/backendCs.Tests/obj/Debug/net8.0/refint/backendCs.Test.dll b/backendCs.Tests/obj/Debug/net8.0/refint/backendCs.Test.dll index 49bd1db..4bb4000 100644 Binary files a/backendCs.Tests/obj/Debug/net8.0/refint/backendCs.Test.dll and b/backendCs.Tests/obj/Debug/net8.0/refint/backendCs.Test.dll differ diff --git a/backendCs/Program.cs b/backendCs/Program.cs index f14101a..e4e51af 100644 --- a/backendCs/Program.cs +++ b/backendCs/Program.cs @@ -15,6 +15,7 @@ namespace Server response.OutputStream.Write(buffer, 0, buffer.Length); response.OutputStream.Write(buffer, 0, buffer.Length); } + static void Main() { // create server @@ -40,13 +41,9 @@ namespace Server // url after localhost:5000/ string uri; if (request != null && request.Url != null) - { uri = request.Url.AbsolutePath; - } else - { return; - } switch (request.HttpMethod) { case "GET": @@ -100,20 +97,6 @@ namespace Server HandleMissingPath(response); break; } - - // try catch is neccessary because if you send a post with no - // body the HTTPLIstener sends response automatically. Which - // would crash the server since i try to send response but - // respose has already been sent. It took me only 2 hours :) - /* try */ - /* { */ - /* // send the response */ - /* response.OutputStream.Close(); */ - /* } */ - /* catch */ - /* { */ - /* Console.WriteLine("Tried sending post with no body"); */ - /* } */ } } } diff --git a/backendCs/Route.cs b/backendCs/Route.cs index 3023924..41d21f2 100644 --- a/backendCs/Route.cs +++ b/backendCs/Route.cs @@ -1,40 +1,40 @@ using System.Net; using System.Text; -using MySql.Data.MySqlClient; -namespace Server +namespace Server; + +public abstract class Route { - abstract public class Route + public static string connectionString = + "server=127.0.0.1;uid=monty;pwd=some_pass;database=timelog"; + + public static void SendError(HttpListenerResponse response, Exception ex) { - - public static string connectionString = "server=127.0.0.1;uid=monty;pwd=some_pass;database=timelog"; - public static void SendError(HttpListenerResponse response, Exception ex) - { - response.StatusCode = (int)HttpStatusCode.BadRequest; - string errorMessage = $"Error: {ex.Message}"; - byte[] buffer = Encoding.UTF8.GetBytes(errorMessage); - response.ContentType = "text/plain"; - response.ContentLength64 = buffer.Length; - response.OutputStream.Write(buffer, 0, buffer.Length); - response.Close(); - } - public static void SendSuccess(HttpListenerResponse response) - { - response.StatusCode = (int)HttpStatusCode.OK; - response.StatusDescription = "Status OK"; - response.Close(); - } - public static void SendSuccess(HttpListenerResponse response, string jsonResponse) - { - response.StatusCode = (int)HttpStatusCode.OK; - response.StatusDescription = "Status OK"; - byte[] buffer = Encoding.UTF8.GetBytes(jsonResponse); - response.ContentType = "application/json"; - response.ContentLength64 = buffer.Length; - response.OutputStream.Write(buffer, 0, buffer.Length); - response.Close(); - } - /* public virtual void run(MySqlConnection conn, HttpListenerRequest request, HttpListenerResponse response) { } */ - + response.StatusCode = (int)HttpStatusCode.BadRequest; + string errorMessage = $"Error: {ex.Message}"; + byte[] buffer = Encoding.UTF8.GetBytes(errorMessage); + response.ContentType = "text/plain"; + response.ContentLength64 = buffer.Length; + response.OutputStream.Write(buffer, 0, buffer.Length); + response.Close(); } + + public static void SendSuccess(HttpListenerResponse response) + { + response.StatusCode = (int)HttpStatusCode.OK; + response.StatusDescription = "Status OK"; + response.Close(); + } + + public static void SendSuccess(HttpListenerResponse response, string jsonResponse) + { + response.StatusCode = (int)HttpStatusCode.OK; + response.StatusDescription = "Status OK"; + byte[] buffer = Encoding.UTF8.GetBytes(jsonResponse); + response.ContentType = "application/json"; + response.ContentLength64 = buffer.Length; + response.OutputStream.Write(buffer, 0, buffer.Length); + response.Close(); + } + /* public virtual void run(MySqlConnection conn, HttpListenerRequest request, HttpListenerResponse response) { } */ } diff --git a/backendCs/bin/Debug/net8.0/TimelogBackend.dll b/backendCs/bin/Debug/net8.0/TimelogBackend.dll index 0080ea1..831f775 100644 Binary files a/backendCs/bin/Debug/net8.0/TimelogBackend.dll and b/backendCs/bin/Debug/net8.0/TimelogBackend.dll differ diff --git a/backendCs/bin/Debug/net8.0/TimelogBackend.pdb b/backendCs/bin/Debug/net8.0/TimelogBackend.pdb index a5e68ed..5863be8 100644 Binary files a/backendCs/bin/Debug/net8.0/TimelogBackend.pdb and b/backendCs/bin/Debug/net8.0/TimelogBackend.pdb differ diff --git a/backendCs/obj/Debug/net8.0/TimelogBackend.AssemblyInfo.cs b/backendCs/obj/Debug/net8.0/TimelogBackend.AssemblyInfo.cs index 4447d4f..d5e7eb6 100644 --- a/backendCs/obj/Debug/net8.0/TimelogBackend.AssemblyInfo.cs +++ b/backendCs/obj/Debug/net8.0/TimelogBackend.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("TimelogBackend")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+8e4317abde8c48644e2bc317481f0f846c577d4b")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+cb7b3ad94c91aad561fa90871a3e078e741f566c")] [assembly: System.Reflection.AssemblyProductAttribute("TimelogBackend")] [assembly: System.Reflection.AssemblyTitleAttribute("TimelogBackend")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/backendCs/obj/Debug/net8.0/TimelogBackend.AssemblyInfoInputs.cache b/backendCs/obj/Debug/net8.0/TimelogBackend.AssemblyInfoInputs.cache index b7aa304..a2b728d 100644 --- a/backendCs/obj/Debug/net8.0/TimelogBackend.AssemblyInfoInputs.cache +++ b/backendCs/obj/Debug/net8.0/TimelogBackend.AssemblyInfoInputs.cache @@ -1 +1 @@ -c543c95dc596bfc3bc702a1cdb58fc473192e89edf57457c326e82da9108ecd6 +21ebdfea2f4ecbc0e48a6b53f27fa496a20e08b7ed0ace43e5500d5093c8a245 diff --git a/backendCs/obj/Debug/net8.0/TimelogBackend.GeneratedMSBuildEditorConfig.editorconfig b/backendCs/obj/Debug/net8.0/TimelogBackend.GeneratedMSBuildEditorConfig.editorconfig index 5a01ff7..294666a 100644 --- a/backendCs/obj/Debug/net8.0/TimelogBackend.GeneratedMSBuildEditorConfig.editorconfig +++ b/backendCs/obj/Debug/net8.0/TimelogBackend.GeneratedMSBuildEditorConfig.editorconfig @@ -8,6 +8,6 @@ build_property.PlatformNeutralAssembly = build_property.EnforceExtendedAnalyzerRules = build_property._SupportedPlatformList = Linux,macOS,Windows build_property.RootNamespace = TimelogBackend -build_property.ProjectDir = /home/arch/projects/wip/timelog-interview-login/backendCs/ +build_property.ProjectDir = /home/arch/projects/unfinished/timelog-interview-login/backendCs/ build_property.EnableComHosting = build_property.EnableGeneratedComInterfaceComImportInterop = diff --git a/backendCs/obj/Debug/net8.0/TimelogBackend.assets.cache b/backendCs/obj/Debug/net8.0/TimelogBackend.assets.cache index 6174452..620bb56 100644 Binary files a/backendCs/obj/Debug/net8.0/TimelogBackend.assets.cache and b/backendCs/obj/Debug/net8.0/TimelogBackend.assets.cache differ diff --git a/backendCs/obj/Debug/net8.0/TimelogBackend.dll b/backendCs/obj/Debug/net8.0/TimelogBackend.dll index 0080ea1..831f775 100644 Binary files a/backendCs/obj/Debug/net8.0/TimelogBackend.dll and b/backendCs/obj/Debug/net8.0/TimelogBackend.dll differ diff --git a/backendCs/obj/Debug/net8.0/TimelogBackend.pdb b/backendCs/obj/Debug/net8.0/TimelogBackend.pdb index a5e68ed..5863be8 100644 Binary files a/backendCs/obj/Debug/net8.0/TimelogBackend.pdb and b/backendCs/obj/Debug/net8.0/TimelogBackend.pdb differ diff --git a/backendCs/obj/Debug/net8.0/ref/TimelogBackend.dll b/backendCs/obj/Debug/net8.0/ref/TimelogBackend.dll index 520158a..805095a 100644 Binary files a/backendCs/obj/Debug/net8.0/ref/TimelogBackend.dll and b/backendCs/obj/Debug/net8.0/ref/TimelogBackend.dll differ diff --git a/backendCs/obj/Debug/net8.0/refint/TimelogBackend.dll b/backendCs/obj/Debug/net8.0/refint/TimelogBackend.dll index 520158a..805095a 100644 Binary files a/backendCs/obj/Debug/net8.0/refint/TimelogBackend.dll and b/backendCs/obj/Debug/net8.0/refint/TimelogBackend.dll differ diff --git a/backendCs/routes/CreateLog.cs b/backendCs/routes/CreateLog.cs index a1cebd9..3f10956 100644 --- a/backendCs/routes/CreateLog.cs +++ b/backendCs/routes/CreateLog.cs @@ -1,17 +1,18 @@ +using System.IdentityModel.Tokens.Jwt; using System.Net; using System.Text; -using MySql.Data.MySqlClient; -using System.IdentityModel.Tokens.Jwt; -using Microsoft.IdentityModel.Tokens; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using System.Text.RegularExpressions; +using Microsoft.IdentityModel.Tokens; +using MySql.Data.MySqlClient; +using Newtonsoft.Json.Linq; namespace Server { public class CreateLog : Route { - private static string secretKey = "stronk-key-much-sercret-much-more-stronk-stronk-key-much-sercret-much-more-stronk"; + private static string secretKey = + "stronk-key-much-sercret-much-more-stronk-stronk-key-much-sercret-much-more-stronk"; + private static bool ValidateToken(string token) { try @@ -25,10 +26,14 @@ namespace Server ValidateLifetime = true, ValidIssuer = "TimeLogServer", ValidAudience = "TimeLogWebsite", - IssuerSigningKey = key + IssuerSigningKey = key, }; - var principal = tokenHandler.ValidateToken(token, validationParameters, out SecurityToken validatedToken); + var principal = tokenHandler.ValidateToken( + token, + validationParameters, + out SecurityToken validatedToken + ); return validatedToken != null; } catch @@ -36,7 +41,12 @@ namespace Server return false; } } - public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response, HttpListenerContext context) + + public static void HandleRequest( + HttpListenerRequest request, + HttpListenerResponse response, + HttpListenerContext context + ) { try { @@ -51,7 +61,12 @@ namespace Server MySqlCommand cmd = new MySqlCommand(); // extact data from body string body; - using (StreamReader bodyReader = new StreamReader(request.InputStream, request.ContentEncoding)) + using ( + StreamReader bodyReader = new StreamReader( + request.InputStream, + request.ContentEncoding + ) + ) { body = bodyReader.ReadToEnd(); } @@ -60,37 +75,41 @@ namespace Server string time = jsonObject["time"]?.ToString() ?? ""; string date = jsonObject["date"]?.ToString() ?? ""; + // TODO check if the hours on given date don't combine to more + // than 8 + // validate time - if (!int.TryParse(time, out int myInt) || myInt < 0) + if (!int.TryParse(time, out int myInt) || myInt < 0 || myInt > 8) throw new Exception("Incorect ammount of hours"); - //validate date + // validate date Regex regex = new Regex(@"^\d{4}-\d{2}-\d{2}$"); if (string.IsNullOrEmpty(date) || !regex.IsMatch(date)) { throw new Exception("Incorrect date format"); } // validate user - // extract user from jwt + // extract user from jwt var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadJwtToken(token); - string? usernameClaim = jwtToken.Claims.FirstOrDefault(c => c.Type == "user")?.Value ?? ""; + string? usernameClaim = + jwtToken.Claims.FirstOrDefault(c => c.Type == "user")?.Value ?? ""; if (string.IsNullOrEmpty(usernameClaim)) { throw new Exception("wrong user id"); } - //validate project + // validate project // TODO better project validation - if (!string.IsNullOrEmpty(project)) + if (string.IsNullOrEmpty(project)) { throw new Exception("wrong project"); } using (MySqlConnection conn = new MySqlConnection(connectionString)) { - conn.Open(); cmd.Connection = conn; - cmd.CommandText = @"INSERT INTO Timelog(user,project,date,time) + cmd.CommandText = + @"INSERT INTO Timelog(user,project,date,time) VALUES(@user,@project,@date,@time);"; cmd.Parameters.AddWithValue("@user", usernameClaim); cmd.Parameters.AddWithValue("@project", project); @@ -109,4 +128,3 @@ namespace Server } } } - diff --git a/backendCs/routes/CreateProcedure.cs b/backendCs/routes/CreateProcedure.cs index 35c8b08..bc40a5b 100644 --- a/backendCs/routes/CreateProcedure.cs +++ b/backendCs/routes/CreateProcedure.cs @@ -1,6 +1,6 @@ using System.Net; -using System.Text; using MySql.Data.MySqlClient; + namespace Server { public class CreateProcedure : Route @@ -15,7 +15,8 @@ namespace Server { conn.Open(); cmd.Connection = conn; - cmd.CommandText = @" + cmd.CommandText = + @" CREATE PROCEDURE fill_timelog () BEGIN DECLARE j INT DEFAULT 1; @@ -53,7 +54,8 @@ BEGIN END WHILE; END;"; cmd.ExecuteNonQuery(); - cmd.CommandText = @"CREATE PROCEDURE InitDB() + cmd.CommandText = + @"CREATE PROCEDURE InitDB() BEGIN DECLARE i INT DEFAULT 1; TRUNCATE TABLE Timelog; diff --git a/backendCs/routes/Getall.cs b/backendCs/routes/Getall.cs index e29a8e6..bc5fc1b 100644 --- a/backendCs/routes/Getall.cs +++ b/backendCs/routes/Getall.cs @@ -1,5 +1,4 @@ using System.Net; -using System.Text; using System.Text.RegularExpressions; using MySql.Data.MySqlClient; using Newtonsoft.Json; @@ -34,11 +33,12 @@ namespace Server string? offset = queryString["offset"]; string? order = queryString["order"]; order = order == "true" ? "ASC" : "DESC"; - // this shenanigan is needed to remove the "" around group by - string mainQuery = @"SELECT u.f_name,u.l_name,u.mail,p.name,t.time,t.date,t.user + string mainQuery = + @"SELECT u.f_name,u.l_name,u.mail,p.name,t.time,t.date,t.user FROM Timelog t INNER JOIN Project p ON p.id=t.project INNER JOIN User u ON u.id=t.user "; + // this shenanigan is needed to remove the "" around group by string offsetQuery = " LIMIT 10 OFFSET " + offset + ";"; // depending on the incoming parameters construct a Query if (!string.IsNullOrEmpty(to) && !string.IsNullOrEmpty(from)) @@ -53,7 +53,16 @@ namespace Server } if (!string.IsNullOrEmpty(sortby)) { - List validSorting = new List { "f_name", "l_name", "mail", "time", "date", "user", }; + List validSorting = new List + { + "f_name", + "l_name", + "mail", + "time", + "date", + "user", + "project", + }; if (!validSorting.Contains(sortby)) { throw new Exception("Incorrect sorting value"); @@ -79,16 +88,18 @@ namespace Server List entries = new List(); while (reader.Read()) { - entries.Add(new Log - { - f_name = reader["f_name"], - l_name = reader["l_name"], - user = reader["user"], - date = reader["date"], - name = reader["name"], - time = reader["time"], - mail = reader["mail"], - }); + entries.Add( + new Log + { + f_name = reader["f_name"], + l_name = reader["l_name"], + user = reader["user"], + date = reader["date"], + name = reader["name"], + time = reader["time"], + mail = reader["mail"], + } + ); } // serialize JSON string jsonResponse = JsonConvert.SerializeObject(entries); diff --git a/backendCs/routes/Gettopten.cs b/backendCs/routes/Gettopten.cs index 8b3314b..dc07f62 100644 --- a/backendCs/routes/Gettopten.cs +++ b/backendCs/routes/Gettopten.cs @@ -1,5 +1,4 @@ using System.Net; -using System.Text; using System.Text.RegularExpressions; using MySql.Data.MySqlClient; using Newtonsoft.Json; @@ -16,6 +15,7 @@ namespace Server public object? name { get; set; } public object? total_time { get; set; } } + public class Gettopten : Route { public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response) @@ -52,12 +52,15 @@ namespace Server // this shenanigan is needed to remove the "" around // group by - string req = @"SELECT t.user,t.date,t.project,u.f_name,u.l_name,p.name,SUM(t.time) as total_time + string req = + @"SELECT t.user,t.date,t.project,u.f_name,u.l_name,p.name,SUM(t.time) as total_time FROM Timelog t INNER JOIN Project p ON p.id=t.project INNER JOIN User u ON u.id=t.user WHERE t.date BETWEEN @from AND @to - GROUP BY " + filterBy + @" ORDER BY total_time DESC + GROUP BY " + + filterBy + + @" ORDER BY total_time DESC LIMIT 10;"; cmd.CommandText = req; cmd.Parameters.AddWithValue("@from", from); @@ -72,22 +75,23 @@ namespace Server List entries = new List(); while (reader.Read()) { - entries.Add(new TopTen - { - user = reader["user"], - date = reader["date"], - project = reader["project"], - f_name = reader["f_name"], - l_name = reader["l_name"], - name = reader["name"], - total_time = reader["total_time"], - }); + entries.Add( + new TopTen + { + user = reader["user"], + date = reader["date"], + project = reader["project"], + f_name = reader["f_name"], + l_name = reader["l_name"], + name = reader["name"], + total_time = reader["total_time"], + } + ); } // Serialize the data to JSON string jsonResponse = JsonConvert.SerializeObject(entries); // prepare response SendSuccess(response, jsonResponse); - } } catch (Exception ex) diff --git a/backendCs/routes/Getuser.cs b/backendCs/routes/Getuser.cs index 0d311a0..50bc7e0 100644 --- a/backendCs/routes/Getuser.cs +++ b/backendCs/routes/Getuser.cs @@ -1,7 +1,6 @@ -using System.Net; -using System.Text; -using MySql.Data.MySqlClient; using System.Dynamic; +using System.Net; +using MySql.Data.MySqlClient; using Newtonsoft.Json; namespace Server @@ -10,19 +9,23 @@ namespace Server { public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response) { - try { + var queryString = request.QueryString; + string? userid = queryString["userid"]; + if (string.IsNullOrEmpty(userid)) + { + throw new Exception("Missing userid"); + } // prepare SQL query MySqlCommand cmd = new MySqlCommand(); - cmd.CommandText = @"SELECT p.name, SUM(t.time) + cmd.CommandText = + @"SELECT p.name, SUM(t.time) FROM Timelog t INNER JOIN Project p ON p.id=t.project INNER JOIN User u ON u.id=t.user WHERE User = @userid GROUP BY name;"; - var queryString = request.QueryString; - string? userid = queryString["userid"]; cmd.Parameters.AddWithValue("@userid", userid); using (MySqlConnection conn = new MySqlConnection(connectionString)) @@ -34,14 +37,14 @@ namespace Server dynamic expando = new ExpandoObject(); while (reader.Read()) { - ((IDictionary)expando)[reader["name"].ToString()] = reader["SUM(t.time)"]; - + ((IDictionary)expando)[reader["name"].ToString()] = reader[ + "SUM(t.time)" + ]; } // serialize JSON string jsonResponse = JsonConvert.SerializeObject(expando); // prepare response SendSuccess(response, jsonResponse); - } } catch (Exception ex) @@ -51,4 +54,3 @@ namespace Server } } } - diff --git a/backendCs/routes/Login.cs b/backendCs/routes/Login.cs index 18278f5..fab2f9a 100644 --- a/backendCs/routes/Login.cs +++ b/backendCs/routes/Login.cs @@ -1,18 +1,19 @@ +using System.IdentityModel.Tokens.Jwt; using System.Net; +using System.Security.Claims; +using System.Security.Cryptography; using System.Text; +using Microsoft.IdentityModel.Tokens; using MySql.Data.MySqlClient; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using System.Security.Claims; -using System.IdentityModel.Tokens.Jwt; -using Microsoft.IdentityModel.Tokens; -using System.Security.Cryptography; namespace Server { public class Login : Route { - private static string secretKey = "stronk-key-much-sercret-much-more-stronk-stronk-key-much-sercret-much-more-stronk"; + private static string secretKey = + "stronk-key-much-sercret-much-more-stronk-stronk-key-much-sercret-much-more-stronk"; public static string GenerateToken(string user) { @@ -22,10 +23,7 @@ namespace Server var token = new JwtSecurityToken( issuer: "TimeLogServer", audience: "TimeLogWebsite", - claims: new[] - { - new Claim("user", user) - }, + claims: new[] { new Claim("user", user) }, expires: DateTime.Now.AddHours(2), signingCredentials: creds ); @@ -42,7 +40,14 @@ namespace Server Array.Copy(hashBytes, 0, salt, 0, 16); // Hash the entered password with the stored salt - using (var pbkdf2 = new Rfc2898DeriveBytes(enteredPassword, salt, 10000, HashAlgorithmName.SHA256)) + using ( + var pbkdf2 = new Rfc2898DeriveBytes( + enteredPassword, + salt, + 10000, + HashAlgorithmName.SHA256 + ) + ) { byte[] newHash = pbkdf2.GetBytes(32); @@ -62,7 +67,12 @@ namespace Server { // extract data from body string body; - using (StreamReader bodyReader = new StreamReader(request.InputStream, request.ContentEncoding)) + using ( + StreamReader bodyReader = new StreamReader( + request.InputStream, + request.ContentEncoding + ) + ) { body = bodyReader.ReadToEnd(); } @@ -72,7 +82,8 @@ namespace Server // prepare SQL query MySqlCommand cmd = new MySqlCommand(); - cmd.CommandText = @"SELECT u.id, password FROM User u + cmd.CommandText = + @"SELECT u.id, password FROM User u INNER JOIN Password p ON p.user=u.id WHERE mail=@mail;"; cmd.Parameters.AddWithValue("@mail", mail); @@ -98,9 +109,11 @@ namespace Server throw new Exception("Invalid Username or Password"); } //check password - if (string.IsNullOrEmpty(password) + if ( + string.IsNullOrEmpty(password) || string.IsNullOrEmpty(hashedPass) - || !VerifyPassword(password, hashedPass)) + || !VerifyPassword(password, hashedPass) + ) { throw new Exception("Invalid Username or Password"); } @@ -118,4 +131,3 @@ namespace Server } } } - diff --git a/backendCs/routes/Register.cs b/backendCs/routes/Register.cs index ba75e5b..a08cf44 100644 --- a/backendCs/routes/Register.cs +++ b/backendCs/routes/Register.cs @@ -1,8 +1,6 @@ using System.Net; -using System.Text; -using MySql.Data.MySqlClient; using System.Security.Cryptography; -using Newtonsoft.Json; +using MySql.Data.MySqlClient; using Newtonsoft.Json.Linq; namespace Server @@ -15,7 +13,9 @@ namespace Server byte[] salt = new byte[16]; RandomNumberGenerator.Fill(salt); // Create a PBKDF2 instance to hash the password - using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000, HashAlgorithmName.SHA256)) + using ( + var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000, HashAlgorithmName.SHA256) + ) { byte[] hash = pbkdf2.GetBytes(32); @@ -28,6 +28,7 @@ namespace Server return Convert.ToBase64String(hashBytes); } } + public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response) { MySqlTransaction? transaction = null; @@ -35,7 +36,12 @@ namespace Server { // extract parameters from req body string body; - using (StreamReader bodyReader = new StreamReader(request.InputStream, request.ContentEncoding)) + using ( + StreamReader bodyReader = new StreamReader( + request.InputStream, + request.ContentEncoding + ) + ) { body = bodyReader.ReadToEnd(); } @@ -46,10 +52,20 @@ namespace Server string mail = jsonObject["mail"]?.ToString() ?? ""; // validate parameters - if (string.IsNullOrEmpty(f_name) || f_name.Length > 30 || f_name.Length < 2 || - string.IsNullOrEmpty(l_name) || l_name.Length > 30 || l_name.Length < 2 || - string.IsNullOrEmpty(mail) || mail.Length > 50 || mail.Length < 6 || - string.IsNullOrEmpty(password) || password.Length > 30 || password.Length < 10) + if ( + string.IsNullOrEmpty(f_name) + || f_name.Length > 30 + || f_name.Length < 2 + || string.IsNullOrEmpty(l_name) + || l_name.Length > 30 + || l_name.Length < 2 + || string.IsNullOrEmpty(mail) + || mail.Length > 50 + || mail.Length < 6 + || string.IsNullOrEmpty(password) + || password.Length > 30 + || password.Length < 10 + ) { throw new Exception("Wrong parameters"); } @@ -58,7 +74,8 @@ namespace Server MySqlCommand cmd = new MySqlCommand(); // Insert into User - cmd.CommandText = "INSERT INTO User(f_name,l_name,mail) VALUES(@f_name,@l_name,@mail)"; + cmd.CommandText = + "INSERT INTO User(f_name,l_name,mail) VALUES(@f_name,@l_name,@mail)"; cmd.Parameters.AddWithValue("@f_name", f_name); cmd.Parameters.AddWithValue("@l_name", l_name); cmd.Parameters.AddWithValue("@mail", mail); diff --git a/backendCs/routes/Reset.cs b/backendCs/routes/Reset.cs index 8f63395..a9e53f6 100644 --- a/backendCs/routes/Reset.cs +++ b/backendCs/routes/Reset.cs @@ -1,5 +1,4 @@ using System.Net; -using System.Text; using MySql.Data.MySqlClient; namespace Server diff --git a/frontend/src/components/CreateLog.tsx b/frontend/src/components/CreateLog.tsx index 9017f90..ad0fd90 100644 --- a/frontend/src/components/CreateLog.tsx +++ b/frontend/src/components/CreateLog.tsx @@ -1,5 +1,6 @@ import { useEffect, useState } from "react"; import api from "../utils/api"; +import { useNavigate } from "react-router-dom"; interface FormInput { project: string; @@ -12,6 +13,7 @@ const CreateLog = ({ authorized }: { authorized: boolean }) => { time: "", date: "", }); + const navigate = useNavigate(); const [token, setToken] = useState(""); useEffect(() => { let tmp = localStorage.getItem("token"); @@ -33,7 +35,11 @@ const CreateLog = ({ authorized }: { authorized: boolean }) => { }, }, ); - console.log(resp); + if (resp.status == 200) { + navigate("/"); + } else { + alert(resp.data); + } } }; const onChange = (e: React.ChangeEvent) => { diff --git a/frontend/src/components/LeftSide.tsx b/frontend/src/components/LeftSide.tsx index 1049ce5..c435529 100644 --- a/frontend/src/components/LeftSide.tsx +++ b/frontend/src/components/LeftSide.tsx @@ -57,8 +57,7 @@ const LeftSide = ({ resetData(); } fetchData(); - // TODO this sends too many request when reseting - console.log(users); + // TODO this way of handling reset sends too many request when reseting }, [reset, params]); const viewProjectHours = (userid: number) => { diff --git a/frontend/src/components/Login.tsx b/frontend/src/components/Login.tsx index 6614d7d..273556f 100644 --- a/frontend/src/components/Login.tsx +++ b/frontend/src/components/Login.tsx @@ -8,8 +8,6 @@ const Login = ({ setAuthorized }: { setAuthorized: Function }) => { const navigate = useNavigate(); const onClick = async () => { const resp = await api.post("/login", { mail, password }); - console.log(resp); - console.log(resp.status); if (resp.status === 200) { localStorage.setItem( "token",