using System.IdentityModel.Tokens.Jwt; using System.Net; using System.Text; using Microsoft.IdentityModel.Tokens; using MySql.Data.MySqlClient; using Newtonsoft.Json.Linq; namespace TimelogBackend; public class CreateLog : Route { private static readonly string secretKey = "stronk-key-much-sercret-much-more-stronk-stronk-key-much-sercret-much-more-stronk"; public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response) { try { // check header var headers = request.Headers; string token = headers["token"] ?? ""; if (!string.IsNullOrEmpty(token) && !ValidateToken(token)) { throw new Exception("Invalid token"); } MySqlCommand cmd = new(); string body; using (StreamReader bodyReader = new(request.InputStream, request.ContentEncoding)) { body = bodyReader.ReadToEnd(); } JObject jsonObject = JObject.Parse(body); string project = jsonObject["project"]?.ToString() ?? ""; 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 if (!ValidateTime(time)) { throw new Exception("Incorrect date format"); } if (!ValidateDate(date)) { throw new Exception("Incorrect date format"); } // validate user string? usernameClaim = GetUserFromToken(token); if (string.IsNullOrEmpty(usernameClaim)) { throw new Exception("wrong user id"); } // validate project // TODO better project validation if (string.IsNullOrEmpty(project)) { throw new Exception("wrong project"); } SaveTimeLogToDatabase(usernameClaim, project, date, time); SendSuccess(response); } catch (Exception ex) { SendError(response, ex); } } private static bool ValidateToken(string token) { try { var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey)); var tokenHandler = new JwtSecurityTokenHandler(); var validationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidIssuer = "TimeLogServer", ValidAudience = "TimeLogWebsite", IssuerSigningKey = key, }; var principal = tokenHandler.ValidateToken( token, validationParameters, out SecurityToken validatedToken ); return validatedToken != null; } catch { return false; } } private static bool ValidateTime(string time) { return int.TryParse(time, out int myInt) && myInt >= 0 && myInt <= 8; } private static string GetUserFromToken(string token) { var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadJwtToken(token); string? usernameClaim = jwtToken.Claims.FirstOrDefault(c => c.Type == "user")?.Value; return string.IsNullOrEmpty(usernameClaim) ? "" : usernameClaim; } private static void SaveTimeLogToDatabase( string username, string project, string date, string time ) { using MySqlConnection conn = new(connectionString); conn.Open(); using MySqlCommand cmd = new( @"INSERT INTO Timelog(user, project, date, time) VALUES(@user, @project, @date, @time);", conn ); cmd.Parameters.AddWithValue("@user", username); cmd.Parameters.AddWithValue("@project", project); cmd.Parameters.AddWithValue("@date", date); cmd.Parameters.AddWithValue("@time", time); cmd.ExecuteNonQuery(); } }