formated all files

This commit is contained in:
QkoSad
2024-12-04 15:46:10 +02:00
parent cb7b3ad94c
commit 926436860c
34 changed files with 360 additions and 169 deletions
+26
View File
@@ -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"
}
]
}
+41
View File
@@ -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"
}
]
}
+94 -21
View File
@@ -1,11 +1,13 @@
namespace backendCs.Test; namespace backendCs.Test;
using System.Net.Http; using System.Net.Http;
using System.Text;
[TestClass] [TestClass]
public class UnitTest1 public class UnitTest1
{ {
[TestMethod] [TestMethod]
async public Task TestMethodReset() public async Task TestMethodReset()
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())
{ {
@@ -16,122 +18,193 @@ public class UnitTest1
Assert.AreEqual<Int32>((int)response.StatusCode, 200); Assert.AreEqual<Int32>((int)response.StatusCode, 200);
} }
} }
[TestMethod] [TestMethod]
async public Task TestMethodGetall1() public async Task TestMethodGetall1()
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())
{ {
// Make a GET request to a URL // 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 // Ensure we have a successful response
Assert.AreEqual<Int32>((int)response.StatusCode, 200); Assert.AreEqual<Int32>((int)response.StatusCode, 200);
} }
} }
[TestMethod] [TestMethod]
async public Task TestMethodGetall2() public async Task TestMethodGetall2()
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())
{ {
// Make a GET request to a URL // 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 // Ensure we have a successful response
Assert.AreEqual<Int32>((int)response.StatusCode, 400); Assert.AreEqual<Int32>((int)response.StatusCode, 400);
} }
} }
async public Task TestMethodGetall3()
[TestMethod]
public async Task TestMethodGetall3()
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())
{ {
// Make a GET request to a URL // 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 // Ensure we have a successful response
Assert.AreEqual<Int32>((int)response.StatusCode, 200); Assert.AreEqual<Int32>((int)response.StatusCode, 200);
} }
} }
[TestMethod] [TestMethod]
async public Task TestMethodGettopten1() public async Task TestMethodGettopten1()
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())
{ {
// Make a GET request to a URL // 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 // Ensure we have a successful response
Assert.AreEqual<Int32>((int)response.StatusCode, 200); Assert.AreEqual<Int32>((int)response.StatusCode, 200);
} }
} }
[TestMethod] [TestMethod]
async public Task TestMethodGettopten2() public async Task TestMethodGettopten2()
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())
{ {
// Make a GET request to a URL // 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 // Ensure we have a successful response
Assert.AreEqual<Int32>((int)response.StatusCode, 200); Assert.AreEqual<Int32>((int)response.StatusCode, 200);
} }
} }
[TestMethod] [TestMethod]
async public Task TestMethodGettopten3() public async Task TestMethodGettopten3()
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())
{ {
// Make a GET request to a URL // 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 // Ensure we have a successful response
Assert.AreEqual<Int32>((int)response.StatusCode, 400); Assert.AreEqual<Int32>((int)response.StatusCode, 400);
} }
} }
[TestMethod] [TestMethod]
async public Task TestMethodGettopten4() public async Task TestMethodGettopten4()
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())
{ {
// Make a GET request to a URL // 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 // Ensure we have a successful response
Assert.AreEqual<Int32>((int)response.StatusCode, 400); Assert.AreEqual<Int32>((int)response.StatusCode, 400);
} }
} }
[TestMethod] [TestMethod]
async public Task TestMethodGettopten5() public async Task TestMethodGettopten5()
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())
{ {
// Make a GET request to a URL // 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 // Ensure we have a successful response
Assert.AreEqual<Int32>((int)response.StatusCode, 400); Assert.AreEqual<Int32>((int)response.StatusCode, 400);
} }
} }
[TestMethod] [TestMethod]
async public Task TestMethodGetuser1() public async Task TestMethodGetuser1()
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())
{ {
// Make a GET request to a URL // 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 // Ensure we have a successful response
Assert.AreEqual<Int32>((int)response.StatusCode, 200); Assert.AreEqual<Int32>((int)response.StatusCode, 200);
} }
} }
async public Task TestMethodGetuser2()
[TestMethod]
public async Task TestMethodGetuser2()
{ {
using (HttpClient client = new HttpClient()) using (HttpClient client = new HttpClient())
{ {
// Make a GET request to a URL // 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 // Ensure we have a successful response
Assert.AreEqual<Int32>((int)response.StatusCode, 400); Assert.AreEqual<Int32>((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<Int32>((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<Int32>((int)response.StatusCode, 200);
}
}
} }
Binary file not shown.
Binary file not shown.
@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("backendCs.Test")] [assembly: System.Reflection.AssemblyCompanyAttribute("backendCs.Test")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [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.AssemblyProductAttribute("backendCs.Test")]
[assembly: System.Reflection.AssemblyTitleAttribute("backendCs.Test")] [assembly: System.Reflection.AssemblyTitleAttribute("backendCs.Test")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
@@ -1 +1 @@
a3618e90ec8e0b41c39e691b17b268fc26531e93f58c71336bc37fefe3594fc9 d5818043832e259ded45b9771c78c909a325898a23799ca0c691beda0cd33197
Binary file not shown.
Binary file not shown.
+1 -18
View File
@@ -15,6 +15,7 @@ namespace Server
response.OutputStream.Write(buffer, 0, buffer.Length); response.OutputStream.Write(buffer, 0, buffer.Length);
response.OutputStream.Write(buffer, 0, buffer.Length); response.OutputStream.Write(buffer, 0, buffer.Length);
} }
static void Main() static void Main()
{ {
// create server // create server
@@ -40,13 +41,9 @@ namespace Server
// url after localhost:5000/ // url after localhost:5000/
string uri; string uri;
if (request != null && request.Url != null) if (request != null && request.Url != null)
{
uri = request.Url.AbsolutePath; uri = request.Url.AbsolutePath;
}
else else
{
return; return;
}
switch (request.HttpMethod) switch (request.HttpMethod)
{ {
case "GET": case "GET":
@@ -100,20 +97,6 @@ namespace Server
HandleMissingPath(response); HandleMissingPath(response);
break; 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"); */
/* } */
} }
} }
} }
+33 -33
View File
@@ -1,40 +1,40 @@
using System.Net; using System.Net;
using System.Text; 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)
{ {
response.StatusCode = (int)HttpStatusCode.BadRequest;
public static string connectionString = "server=127.0.0.1;uid=monty;pwd=some_pass;database=timelog"; string errorMessage = $"Error: {ex.Message}";
public static void SendError(HttpListenerResponse response, Exception ex) byte[] buffer = Encoding.UTF8.GetBytes(errorMessage);
{ response.ContentType = "text/plain";
response.StatusCode = (int)HttpStatusCode.BadRequest; response.ContentLength64 = buffer.Length;
string errorMessage = $"Error: {ex.Message}"; response.OutputStream.Write(buffer, 0, buffer.Length);
byte[] buffer = Encoding.UTF8.GetBytes(errorMessage); response.Close();
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) { } */
} }
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) { } */
} }
Binary file not shown.
Binary file not shown.
@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("TimelogBackend")] [assembly: System.Reflection.AssemblyCompanyAttribute("TimelogBackend")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [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.AssemblyProductAttribute("TimelogBackend")]
[assembly: System.Reflection.AssemblyTitleAttribute("TimelogBackend")] [assembly: System.Reflection.AssemblyTitleAttribute("TimelogBackend")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
@@ -1 +1 @@
c543c95dc596bfc3bc702a1cdb58fc473192e89edf57457c326e82da9108ecd6 21ebdfea2f4ecbc0e48a6b53f27fa496a20e08b7ed0ace43e5500d5093c8a245
@@ -8,6 +8,6 @@ build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules = build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = TimelogBackend 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.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop = build_property.EnableGeneratedComInterfaceComImportInterop =
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+36 -18
View File
@@ -1,17 +1,18 @@
using System.IdentityModel.Tokens.Jwt;
using System.Net; using System.Net;
using System.Text; 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 System.Text.RegularExpressions;
using Microsoft.IdentityModel.Tokens;
using MySql.Data.MySqlClient;
using Newtonsoft.Json.Linq;
namespace Server namespace Server
{ {
public class CreateLog : Route 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) private static bool ValidateToken(string token)
{ {
try try
@@ -25,10 +26,14 @@ namespace Server
ValidateLifetime = true, ValidateLifetime = true,
ValidIssuer = "TimeLogServer", ValidIssuer = "TimeLogServer",
ValidAudience = "TimeLogWebsite", 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; return validatedToken != null;
} }
catch catch
@@ -36,7 +41,12 @@ namespace Server
return false; return false;
} }
} }
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response, HttpListenerContext context)
public static void HandleRequest(
HttpListenerRequest request,
HttpListenerResponse response,
HttpListenerContext context
)
{ {
try try
{ {
@@ -51,7 +61,12 @@ namespace Server
MySqlCommand cmd = new MySqlCommand(); MySqlCommand cmd = new MySqlCommand();
// extact data from body // extact data from body
string body; string body;
using (StreamReader bodyReader = new StreamReader(request.InputStream, request.ContentEncoding)) using (
StreamReader bodyReader = new StreamReader(
request.InputStream,
request.ContentEncoding
)
)
{ {
body = bodyReader.ReadToEnd(); body = bodyReader.ReadToEnd();
} }
@@ -60,10 +75,13 @@ namespace Server
string time = jsonObject["time"]?.ToString() ?? ""; string time = jsonObject["time"]?.ToString() ?? "";
string date = jsonObject["date"]?.ToString() ?? ""; string date = jsonObject["date"]?.ToString() ?? "";
// TODO check if the hours on given date don't combine to more
// than 8
// validate time // 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"); throw new Exception("Incorect ammount of hours");
//validate date // validate date
Regex regex = new Regex(@"^\d{4}-\d{2}-\d{2}$"); Regex regex = new Regex(@"^\d{4}-\d{2}-\d{2}$");
if (string.IsNullOrEmpty(date) || !regex.IsMatch(date)) if (string.IsNullOrEmpty(date) || !regex.IsMatch(date))
{ {
@@ -73,24 +91,25 @@ namespace Server
// extract user from jwt // extract user from jwt
var handler = new JwtSecurityTokenHandler(); var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadJwtToken(token); 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)) if (string.IsNullOrEmpty(usernameClaim))
{ {
throw new Exception("wrong user id"); throw new Exception("wrong user id");
} }
//validate project // validate project
// TODO better project validation // TODO better project validation
if (!string.IsNullOrEmpty(project)) if (string.IsNullOrEmpty(project))
{ {
throw new Exception("wrong project"); throw new Exception("wrong project");
} }
using (MySqlConnection conn = new MySqlConnection(connectionString)) using (MySqlConnection conn = new MySqlConnection(connectionString))
{ {
conn.Open(); conn.Open();
cmd.Connection = conn; 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);"; VALUES(@user,@project,@date,@time);";
cmd.Parameters.AddWithValue("@user", usernameClaim); cmd.Parameters.AddWithValue("@user", usernameClaim);
cmd.Parameters.AddWithValue("@project", project); cmd.Parameters.AddWithValue("@project", project);
@@ -109,4 +128,3 @@ namespace Server
} }
} }
} }
+5 -3
View File
@@ -1,6 +1,6 @@
using System.Net; using System.Net;
using System.Text;
using MySql.Data.MySqlClient; using MySql.Data.MySqlClient;
namespace Server namespace Server
{ {
public class CreateProcedure : Route public class CreateProcedure : Route
@@ -15,7 +15,8 @@ namespace Server
{ {
conn.Open(); conn.Open();
cmd.Connection = conn; cmd.Connection = conn;
cmd.CommandText = @" cmd.CommandText =
@"
CREATE PROCEDURE fill_timelog () CREATE PROCEDURE fill_timelog ()
BEGIN BEGIN
DECLARE j INT DEFAULT 1; DECLARE j INT DEFAULT 1;
@@ -53,7 +54,8 @@ BEGIN
END WHILE; END WHILE;
END;"; END;";
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
cmd.CommandText = @"CREATE PROCEDURE InitDB() cmd.CommandText =
@"CREATE PROCEDURE InitDB()
BEGIN BEGIN
DECLARE i INT DEFAULT 1; DECLARE i INT DEFAULT 1;
TRUNCATE TABLE Timelog; TRUNCATE TABLE Timelog;
+25 -14
View File
@@ -1,5 +1,4 @@
using System.Net; using System.Net;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using MySql.Data.MySqlClient; using MySql.Data.MySqlClient;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -34,11 +33,12 @@ namespace Server
string? offset = queryString["offset"]; string? offset = queryString["offset"];
string? order = queryString["order"]; string? order = queryString["order"];
order = order == "true" ? "ASC" : "DESC"; order = order == "true" ? "ASC" : "DESC";
// this shenanigan is needed to remove the "" around group by string mainQuery =
string mainQuery = @"SELECT u.f_name,u.l_name,u.mail,p.name,t.time,t.date,t.user @"SELECT u.f_name,u.l_name,u.mail,p.name,t.time,t.date,t.user
FROM Timelog t FROM Timelog t
INNER JOIN Project p ON p.id=t.project INNER JOIN Project p ON p.id=t.project
INNER JOIN User u ON u.id=t.user "; 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 + ";"; string offsetQuery = " LIMIT 10 OFFSET " + offset + ";";
// depending on the incoming parameters construct a Query // depending on the incoming parameters construct a Query
if (!string.IsNullOrEmpty(to) && !string.IsNullOrEmpty(from)) if (!string.IsNullOrEmpty(to) && !string.IsNullOrEmpty(from))
@@ -53,7 +53,16 @@ namespace Server
} }
if (!string.IsNullOrEmpty(sortby)) if (!string.IsNullOrEmpty(sortby))
{ {
List<string> validSorting = new List<string> { "f_name", "l_name", "mail", "time", "date", "user", }; List<string> validSorting = new List<string>
{
"f_name",
"l_name",
"mail",
"time",
"date",
"user",
"project",
};
if (!validSorting.Contains(sortby)) if (!validSorting.Contains(sortby))
{ {
throw new Exception("Incorrect sorting value"); throw new Exception("Incorrect sorting value");
@@ -79,16 +88,18 @@ namespace Server
List<Log> entries = new List<Log>(); List<Log> entries = new List<Log>();
while (reader.Read()) while (reader.Read())
{ {
entries.Add(new Log entries.Add(
{ new Log
f_name = reader["f_name"], {
l_name = reader["l_name"], f_name = reader["f_name"],
user = reader["user"], l_name = reader["l_name"],
date = reader["date"], user = reader["user"],
name = reader["name"], date = reader["date"],
time = reader["time"], name = reader["name"],
mail = reader["mail"], time = reader["time"],
}); mail = reader["mail"],
}
);
} }
// serialize JSON // serialize JSON
string jsonResponse = JsonConvert.SerializeObject(entries); string jsonResponse = JsonConvert.SerializeObject(entries);
+18 -14
View File
@@ -1,5 +1,4 @@
using System.Net; using System.Net;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using MySql.Data.MySqlClient; using MySql.Data.MySqlClient;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -16,6 +15,7 @@ namespace Server
public object? name { get; set; } public object? name { get; set; }
public object? total_time { get; set; } public object? total_time { get; set; }
} }
public class Gettopten : Route public class Gettopten : Route
{ {
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response) public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
@@ -52,12 +52,15 @@ namespace Server
// this shenanigan is needed to remove the "" around // this shenanigan is needed to remove the "" around
// group by // 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 FROM Timelog t
INNER JOIN Project p ON p.id=t.project INNER JOIN Project p ON p.id=t.project
INNER JOIN User u ON u.id=t.user INNER JOIN User u ON u.id=t.user
WHERE t.date BETWEEN @from AND @to 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;"; LIMIT 10;";
cmd.CommandText = req; cmd.CommandText = req;
cmd.Parameters.AddWithValue("@from", from); cmd.Parameters.AddWithValue("@from", from);
@@ -72,22 +75,23 @@ namespace Server
List<TopTen> entries = new List<TopTen>(); List<TopTen> entries = new List<TopTen>();
while (reader.Read()) while (reader.Read())
{ {
entries.Add(new TopTen entries.Add(
{ new TopTen
user = reader["user"], {
date = reader["date"], user = reader["user"],
project = reader["project"], date = reader["date"],
f_name = reader["f_name"], project = reader["project"],
l_name = reader["l_name"], f_name = reader["f_name"],
name = reader["name"], l_name = reader["l_name"],
total_time = reader["total_time"], name = reader["name"],
}); total_time = reader["total_time"],
}
);
} }
// Serialize the data to JSON // Serialize the data to JSON
string jsonResponse = JsonConvert.SerializeObject(entries); string jsonResponse = JsonConvert.SerializeObject(entries);
// prepare response // prepare response
SendSuccess(response, jsonResponse); SendSuccess(response, jsonResponse);
} }
} }
catch (Exception ex) catch (Exception ex)
+13 -11
View File
@@ -1,7 +1,6 @@
using System.Net;
using System.Text;
using MySql.Data.MySqlClient;
using System.Dynamic; using System.Dynamic;
using System.Net;
using MySql.Data.MySqlClient;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Server namespace Server
@@ -10,19 +9,23 @@ namespace Server
{ {
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response) public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
{ {
try try
{ {
var queryString = request.QueryString;
string? userid = queryString["userid"];
if (string.IsNullOrEmpty(userid))
{
throw new Exception("Missing userid");
}
// prepare SQL query // prepare SQL query
MySqlCommand cmd = new MySqlCommand(); MySqlCommand cmd = new MySqlCommand();
cmd.CommandText = @"SELECT p.name, SUM(t.time) cmd.CommandText =
@"SELECT p.name, SUM(t.time)
FROM Timelog t FROM Timelog t
INNER JOIN Project p ON p.id=t.project INNER JOIN Project p ON p.id=t.project
INNER JOIN User u ON u.id=t.user INNER JOIN User u ON u.id=t.user
WHERE User = @userid WHERE User = @userid
GROUP BY name;"; GROUP BY name;";
var queryString = request.QueryString;
string? userid = queryString["userid"];
cmd.Parameters.AddWithValue("@userid", userid); cmd.Parameters.AddWithValue("@userid", userid);
using (MySqlConnection conn = new MySqlConnection(connectionString)) using (MySqlConnection conn = new MySqlConnection(connectionString))
@@ -34,14 +37,14 @@ namespace Server
dynamic expando = new ExpandoObject(); dynamic expando = new ExpandoObject();
while (reader.Read()) while (reader.Read())
{ {
((IDictionary<string?, object>)expando)[reader["name"].ToString()] = reader["SUM(t.time)"]; ((IDictionary<string?, object>)expando)[reader["name"].ToString()] = reader[
"SUM(t.time)"
];
} }
// serialize JSON // serialize JSON
string jsonResponse = JsonConvert.SerializeObject(expando); string jsonResponse = JsonConvert.SerializeObject(expando);
// prepare response // prepare response
SendSuccess(response, jsonResponse); SendSuccess(response, jsonResponse);
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -51,4 +54,3 @@ namespace Server
} }
} }
} }
+27 -15
View File
@@ -1,18 +1,19 @@
using System.IdentityModel.Tokens.Jwt;
using System.Net; using System.Net;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text; using System.Text;
using Microsoft.IdentityModel.Tokens;
using MySql.Data.MySqlClient; using MySql.Data.MySqlClient;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System.Security.Claims;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.Security.Cryptography;
namespace Server namespace Server
{ {
public class Login : Route 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) public static string GenerateToken(string user)
{ {
@@ -22,10 +23,7 @@ namespace Server
var token = new JwtSecurityToken( var token = new JwtSecurityToken(
issuer: "TimeLogServer", issuer: "TimeLogServer",
audience: "TimeLogWebsite", audience: "TimeLogWebsite",
claims: new[] claims: new[] { new Claim("user", user) },
{
new Claim("user", user)
},
expires: DateTime.Now.AddHours(2), expires: DateTime.Now.AddHours(2),
signingCredentials: creds signingCredentials: creds
); );
@@ -42,7 +40,14 @@ namespace Server
Array.Copy(hashBytes, 0, salt, 0, 16); Array.Copy(hashBytes, 0, salt, 0, 16);
// Hash the entered password with the stored salt // 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); byte[] newHash = pbkdf2.GetBytes(32);
@@ -62,7 +67,12 @@ namespace Server
{ {
// extract data from body // extract data from body
string body; string body;
using (StreamReader bodyReader = new StreamReader(request.InputStream, request.ContentEncoding)) using (
StreamReader bodyReader = new StreamReader(
request.InputStream,
request.ContentEncoding
)
)
{ {
body = bodyReader.ReadToEnd(); body = bodyReader.ReadToEnd();
} }
@@ -72,7 +82,8 @@ namespace Server
// prepare SQL query // prepare SQL query
MySqlCommand cmd = new MySqlCommand(); 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 INNER JOIN Password p ON p.user=u.id
WHERE mail=@mail;"; WHERE mail=@mail;";
cmd.Parameters.AddWithValue("@mail", mail); cmd.Parameters.AddWithValue("@mail", mail);
@@ -98,9 +109,11 @@ namespace Server
throw new Exception("Invalid Username or Password"); throw new Exception("Invalid Username or Password");
} }
//check password //check password
if (string.IsNullOrEmpty(password) if (
string.IsNullOrEmpty(password)
|| string.IsNullOrEmpty(hashedPass) || string.IsNullOrEmpty(hashedPass)
|| !VerifyPassword(password, hashedPass)) || !VerifyPassword(password, hashedPass)
)
{ {
throw new Exception("Invalid Username or Password"); throw new Exception("Invalid Username or Password");
} }
@@ -118,4 +131,3 @@ namespace Server
} }
} }
} }
+27 -10
View File
@@ -1,8 +1,6 @@
using System.Net; using System.Net;
using System.Text;
using MySql.Data.MySqlClient;
using System.Security.Cryptography; using System.Security.Cryptography;
using Newtonsoft.Json; using MySql.Data.MySqlClient;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
namespace Server namespace Server
@@ -15,7 +13,9 @@ namespace Server
byte[] salt = new byte[16]; byte[] salt = new byte[16];
RandomNumberGenerator.Fill(salt); RandomNumberGenerator.Fill(salt);
// Create a PBKDF2 instance to hash the password // 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); byte[] hash = pbkdf2.GetBytes(32);
@@ -28,6 +28,7 @@ namespace Server
return Convert.ToBase64String(hashBytes); return Convert.ToBase64String(hashBytes);
} }
} }
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response) public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
{ {
MySqlTransaction? transaction = null; MySqlTransaction? transaction = null;
@@ -35,7 +36,12 @@ namespace Server
{ {
// extract parameters from req body // extract parameters from req body
string body; string body;
using (StreamReader bodyReader = new StreamReader(request.InputStream, request.ContentEncoding)) using (
StreamReader bodyReader = new StreamReader(
request.InputStream,
request.ContentEncoding
)
)
{ {
body = bodyReader.ReadToEnd(); body = bodyReader.ReadToEnd();
} }
@@ -46,10 +52,20 @@ namespace Server
string mail = jsonObject["mail"]?.ToString() ?? ""; string mail = jsonObject["mail"]?.ToString() ?? "";
// validate parameters // validate parameters
if (string.IsNullOrEmpty(f_name) || f_name.Length > 30 || f_name.Length < 2 || if (
string.IsNullOrEmpty(l_name) || l_name.Length > 30 || l_name.Length < 2 || string.IsNullOrEmpty(f_name)
string.IsNullOrEmpty(mail) || mail.Length > 50 || mail.Length < 6 || || f_name.Length > 30
string.IsNullOrEmpty(password) || password.Length > 30 || password.Length < 10) || 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"); throw new Exception("Wrong parameters");
} }
@@ -58,7 +74,8 @@ namespace Server
MySqlCommand cmd = new MySqlCommand(); MySqlCommand cmd = new MySqlCommand();
// Insert into User // 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("@f_name", f_name);
cmd.Parameters.AddWithValue("@l_name", l_name); cmd.Parameters.AddWithValue("@l_name", l_name);
cmd.Parameters.AddWithValue("@mail", mail); cmd.Parameters.AddWithValue("@mail", mail);
-1
View File
@@ -1,5 +1,4 @@
using System.Net; using System.Net;
using System.Text;
using MySql.Data.MySqlClient; using MySql.Data.MySqlClient;
namespace Server namespace Server
+7 -1
View File
@@ -1,5 +1,6 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import api from "../utils/api"; import api from "../utils/api";
import { useNavigate } from "react-router-dom";
interface FormInput { interface FormInput {
project: string; project: string;
@@ -12,6 +13,7 @@ const CreateLog = ({ authorized }: { authorized: boolean }) => {
time: "", time: "",
date: "", date: "",
}); });
const navigate = useNavigate();
const [token, setToken] = useState<String>(""); const [token, setToken] = useState<String>("");
useEffect(() => { useEffect(() => {
let tmp = localStorage.getItem("token"); 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<HTMLInputElement>) => { const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+1 -2
View File
@@ -57,8 +57,7 @@ const LeftSide = ({
resetData(); resetData();
} }
fetchData(); fetchData();
// TODO this sends too many request when reseting // TODO this way of handling reset sends too many request when reseting
console.log(users);
}, [reset, params]); }, [reset, params]);
const viewProjectHours = (userid: number) => { const viewProjectHours = (userid: number) => {
-2
View File
@@ -8,8 +8,6 @@ const Login = ({ setAuthorized }: { setAuthorized: Function }) => {
const navigate = useNavigate(); const navigate = useNavigate();
const onClick = async () => { const onClick = async () => {
const resp = await api.post("/login", { mail, password }); const resp = await api.post("/login", { mail, password });
console.log(resp);
console.log(resp.status);
if (resp.status === 200) { if (resp.status === 200) {
localStorage.setItem( localStorage.setItem(
"token", "token",