fighting weird bug with branches
This commit is contained in:
-1
Submodule Server deleted from 4de9704470
@@ -0,0 +1,48 @@
|
|||||||
|
using System.Net;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class CreateComment : SecuredRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<string> bodyParamNames = ["message", "post"];
|
||||||
|
string user_id = ExtractUserId(request);
|
||||||
|
var bodyParamValues = ExtractBody(request, bodyParamNames);
|
||||||
|
ValidateParams(bodyParamValues);
|
||||||
|
|
||||||
|
bodyParamNames.Add("user_id");
|
||||||
|
bodyParamValues["user_id"] = user_id;
|
||||||
|
|
||||||
|
MySqlCommand cmd = new(CreateInsertQuery("comment", bodyParamNames));
|
||||||
|
|
||||||
|
cmd = AddValuesToCmd(bodyParamValues, cmd);
|
||||||
|
|
||||||
|
using MySqlConnection conn = new(connectionString);
|
||||||
|
conn.Open();
|
||||||
|
cmd.Connection = conn;
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ValidateParams(Dictionary<string, string> paramsToValidate)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
if (!int.TryParse(paramsToValidate["post"], out int myInt) || myInt < 0)
|
||||||
|
throw new Exception("Incorect post");
|
||||||
|
}
|
||||||
|
if (paramsToValidate["message"].Length > 1000)
|
||||||
|
{
|
||||||
|
throw new Exception("Wrong parameters");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
using System.Net;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class CreateEducation : SecuredRoute
|
||||||
|
{
|
||||||
|
private static void ValidateParams(Dictionary<string, string> paramsToValidate)
|
||||||
|
{
|
||||||
|
string format = "yyyy-MM-dd";
|
||||||
|
if (
|
||||||
|
paramsToValidate["school"].Length > 70
|
||||||
|
|| string.IsNullOrEmpty(paramsToValidate["school"])
|
||||||
|
|| paramsToValidate["degree"].Length > 120
|
||||||
|
|| string.IsNullOrEmpty(paramsToValidate["degree"])
|
||||||
|
|| paramsToValidate["field"].Length > 100
|
||||||
|
|| string.IsNullOrEmpty(paramsToValidate["field"])
|
||||||
|
|| !DateTime.TryParseExact(
|
||||||
|
paramsToValidate["from_date"],
|
||||||
|
format,
|
||||||
|
null,
|
||||||
|
System.Globalization.DateTimeStyles.None,
|
||||||
|
out _
|
||||||
|
)
|
||||||
|
|| !DateTime.TryParseExact(
|
||||||
|
paramsToValidate["to_date"],
|
||||||
|
format,
|
||||||
|
null,
|
||||||
|
System.Globalization.DateTimeStyles.None,
|
||||||
|
out _
|
||||||
|
)
|
||||||
|
|| paramsToValidate["description"].Length > 1000
|
||||||
|
)
|
||||||
|
{
|
||||||
|
throw new Exception("Wrong parameters");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<string> bodyParamNames =
|
||||||
|
[
|
||||||
|
"school",
|
||||||
|
"degree",
|
||||||
|
"field",
|
||||||
|
"from_date",
|
||||||
|
"to_date",
|
||||||
|
"description",
|
||||||
|
];
|
||||||
|
string user_id = ExtractUserId(request);
|
||||||
|
var bodyParamValues = ExtractBody(request, bodyParamNames);
|
||||||
|
ValidateParams(bodyParamValues);
|
||||||
|
|
||||||
|
bodyParamNames.Add("user_id");
|
||||||
|
bodyParamValues["user_id"] = user_id;
|
||||||
|
|
||||||
|
MySqlCommand cmd = new(CreateInsertQuery("education", bodyParamNames));
|
||||||
|
|
||||||
|
cmd = AddValuesToCmd(bodyParamValues, cmd);
|
||||||
|
|
||||||
|
using MySqlConnection conn = new(connectionString);
|
||||||
|
conn.Open();
|
||||||
|
cmd.Connection = conn;
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
using System.Net;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class CreateExperience : SecuredRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<string> bodyParamNames =
|
||||||
|
[
|
||||||
|
"job",
|
||||||
|
"company",
|
||||||
|
"location",
|
||||||
|
"from_date",
|
||||||
|
"to_date",
|
||||||
|
"description",
|
||||||
|
];
|
||||||
|
string user_id = ExtractUserId(request);
|
||||||
|
var bodyParamValues = ExtractBody(request, bodyParamNames);
|
||||||
|
ValidateParams(bodyParamValues);
|
||||||
|
|
||||||
|
bodyParamNames.Add("user_id");
|
||||||
|
bodyParamValues["user_id"] = user_id;
|
||||||
|
|
||||||
|
MySqlCommand cmd = new(CreateInsertQuery("experience", bodyParamNames));
|
||||||
|
|
||||||
|
cmd = AddValuesToCmd(bodyParamValues, cmd);
|
||||||
|
|
||||||
|
using MySqlConnection conn = new(connectionString);
|
||||||
|
conn.Open();
|
||||||
|
cmd.Connection = conn;
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ValidateParams(Dictionary<string, string> paramsToValidate)
|
||||||
|
{
|
||||||
|
string format = "yyyy-MM-dd";
|
||||||
|
if (
|
||||||
|
paramsToValidate["job"].Length > 70
|
||||||
|
|| string.IsNullOrEmpty(paramsToValidate["job"])
|
||||||
|
|| paramsToValidate["company"].Length > 120
|
||||||
|
|| string.IsNullOrEmpty(paramsToValidate["company"])
|
||||||
|
|| paramsToValidate["location"].Length > 100
|
||||||
|
|| string.IsNullOrEmpty(paramsToValidate["location"])
|
||||||
|
|| !DateTime.TryParseExact(
|
||||||
|
paramsToValidate["from_date"],
|
||||||
|
format,
|
||||||
|
null,
|
||||||
|
System.Globalization.DateTimeStyles.None,
|
||||||
|
out _
|
||||||
|
)
|
||||||
|
|| !DateTime.TryParseExact(
|
||||||
|
paramsToValidate["to_date"],
|
||||||
|
format,
|
||||||
|
null,
|
||||||
|
System.Globalization.DateTimeStyles.None,
|
||||||
|
out _
|
||||||
|
)
|
||||||
|
|| paramsToValidate["description"].Length > 1000
|
||||||
|
)
|
||||||
|
{
|
||||||
|
throw new Exception("Wrong parameters");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
using System.Net;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class CreatePost : SecuredRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<string> bodyParamNames = ["message"];
|
||||||
|
string user_id = ExtractUserId(request);
|
||||||
|
var bodyParamValues = ExtractBody(request, bodyParamNames);
|
||||||
|
ValidateParams(bodyParamValues);
|
||||||
|
|
||||||
|
bodyParamNames.Add("user_id");
|
||||||
|
bodyParamValues["user_id"] = user_id;
|
||||||
|
|
||||||
|
MySqlCommand cmd = new(CreateInsertQuery("post", bodyParamNames));
|
||||||
|
|
||||||
|
cmd = AddValuesToCmd(bodyParamValues, cmd);
|
||||||
|
|
||||||
|
using MySqlConnection conn = new(connectionString);
|
||||||
|
conn.Open();
|
||||||
|
cmd.Connection = conn;
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ValidateParams(Dictionary<string, string> paramsToValidate)
|
||||||
|
{
|
||||||
|
if (paramsToValidate["message"].Length > 1000)
|
||||||
|
{
|
||||||
|
throw new Exception("Wrong parameters");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
using System.Net;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class CreateProfile : SecuredRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<string> bodyParamNames =
|
||||||
|
[
|
||||||
|
"f_name",
|
||||||
|
"l_name",
|
||||||
|
"company",
|
||||||
|
"website",
|
||||||
|
"location",
|
||||||
|
"github",
|
||||||
|
"status",
|
||||||
|
"bio",
|
||||||
|
"skills",
|
||||||
|
"twitter",
|
||||||
|
"facebook",
|
||||||
|
"youtube",
|
||||||
|
"linkedin",
|
||||||
|
"instagram",
|
||||||
|
];
|
||||||
|
string user_id = ExtractUserId(request);
|
||||||
|
var bodyParamValues = ExtractBody(request, bodyParamNames);
|
||||||
|
ValidateParams(bodyParamValues);
|
||||||
|
|
||||||
|
bodyParamNames.Add("user_id");
|
||||||
|
bodyParamValues["user_id"] = user_id;
|
||||||
|
|
||||||
|
MySqlCommand cmd = new(CreateInsertQuery("profile", bodyParamNames));
|
||||||
|
|
||||||
|
cmd = AddValuesToCmd(bodyParamValues, cmd);
|
||||||
|
|
||||||
|
using MySqlConnection conn = new(connectionString);
|
||||||
|
conn.Open();
|
||||||
|
cmd.Connection = conn;
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ValidateParams(Dictionary<string, string> paramsToValidate)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
paramsToValidate["f_name"].Length > 30
|
||||||
|
|| string.IsNullOrEmpty(paramsToValidate["f_name"])
|
||||||
|
|| paramsToValidate["l_name"].Length > 30
|
||||||
|
|| string.IsNullOrEmpty(paramsToValidate["l_name"])
|
||||||
|
|| paramsToValidate["company"].Length > 70
|
||||||
|
|| string.IsNullOrEmpty(paramsToValidate["company"])
|
||||||
|
|| paramsToValidate["website"].Length > 120
|
||||||
|
|| paramsToValidate["location"].Length > 100
|
||||||
|
|| string.IsNullOrEmpty(paramsToValidate["location"])
|
||||||
|
|| paramsToValidate["skills"].Length > 300
|
||||||
|
|| paramsToValidate["github"].Length > 120
|
||||||
|
|| paramsToValidate["status"].Length > 20
|
||||||
|
|| string.IsNullOrEmpty(paramsToValidate["status"])
|
||||||
|
|| paramsToValidate["bio"].Length > 1000
|
||||||
|
|| paramsToValidate["twitter"].Length > 100
|
||||||
|
|| paramsToValidate["facebook"].Length > 100
|
||||||
|
|| paramsToValidate["youtube"].Length > 100
|
||||||
|
|| paramsToValidate["linkedin"].Length > 100
|
||||||
|
|| paramsToValidate["instagram"].Length > 100
|
||||||
|
)
|
||||||
|
{
|
||||||
|
throw new Exception("Wrong parameters");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class DeleteComment : DeleteRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DeleteFromDB(request, "comment", ["id"], true);
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class DeleteEducation : DeleteRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DeleteFromDB(request, "education", ["id"], true);
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class DeleteExperience : DeleteRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DeleteFromDB(request, "education", ["id"], true);
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class DeletePost : DeleteRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DeleteFromDB(request, "post", ["id"], true);
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class DeleteProfile : DeleteRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DeleteFromDB(request, "profile", ["id"], false);
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using System.Net;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class DeleteRoute : SecuredRoute
|
||||||
|
{
|
||||||
|
protected static void DeleteFromDB(
|
||||||
|
HttpListenerRequest request,
|
||||||
|
string table,
|
||||||
|
List<string> validParamNames,
|
||||||
|
bool requireId
|
||||||
|
)
|
||||||
|
// TODO should return error when it cant find the comment
|
||||||
|
{
|
||||||
|
// extract userid compare userid to the comment userid
|
||||||
|
string user_id = ExtractUserId(request);
|
||||||
|
var bodyParamValues = ExtractBody(request, validParamNames);
|
||||||
|
|
||||||
|
if (requireId && bodyParamValues["id"] is null)
|
||||||
|
throw new Exception("missing id");
|
||||||
|
|
||||||
|
validParamNames.Add("user_id");
|
||||||
|
bodyParamValues["user_id"] = user_id;
|
||||||
|
table += requireId ? " Where user_id=@user_id;" : " WHERE id=@id AND user_id=@user_id;";
|
||||||
|
MySqlCommand cmd = new("DELETE from " + table);
|
||||||
|
|
||||||
|
cmd = AddValuesToCmd(bodyParamValues, cmd);
|
||||||
|
|
||||||
|
using MySqlConnection conn = new(connectionString);
|
||||||
|
conn.Open();
|
||||||
|
cmd.Connection = conn;
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class Login : SecuredRoute
|
||||||
|
{
|
||||||
|
private static void ValidateParams(Dictionary<string, string> paramsToValidate)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
string.IsNullOrEmpty(paramsToValidate["email"])
|
||||||
|
|| string.IsNullOrEmpty(paramsToValidate["password"])
|
||||||
|
)
|
||||||
|
throw new Exception("Invalid parameters");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<string> bodyParamNames = ["email", "password"];
|
||||||
|
var bodyParamValues = ExtractBody(request, bodyParamNames);
|
||||||
|
ValidateParams(bodyParamValues);
|
||||||
|
|
||||||
|
string query =
|
||||||
|
@"SELECT id, password FROM user
|
||||||
|
WHERE email=@email;";
|
||||||
|
MySqlCommand cmd = new(query);
|
||||||
|
cmd.Parameters.AddWithValue("@email", bodyParamValues["email"]);
|
||||||
|
|
||||||
|
var userId = ExtractUserIdFromDB(cmd, bodyParamValues["password"]);
|
||||||
|
|
||||||
|
string? jsonResponse = JsonConvert.SerializeObject(GenerateToken(userId));
|
||||||
|
// prepare response
|
||||||
|
SendSuccess(response, jsonResponse);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ExtractUserIdFromDB(MySqlCommand cmd, string password)
|
||||||
|
{
|
||||||
|
using MySqlConnection conn = new(connectionString);
|
||||||
|
cmd.Connection = conn;
|
||||||
|
conn.Open();
|
||||||
|
// execute query and read results
|
||||||
|
MySqlDataReader reader = cmd.ExecuteReader();
|
||||||
|
string? userId = "";
|
||||||
|
string? hashedPass = "";
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
userId = Convert.ToString(reader["id"]);
|
||||||
|
hashedPass = reader.GetString("password");
|
||||||
|
}
|
||||||
|
// check username
|
||||||
|
if (string.IsNullOrEmpty(userId))
|
||||||
|
{
|
||||||
|
throw new Exception("Invalid Username or Password");
|
||||||
|
}
|
||||||
|
//check password
|
||||||
|
if (
|
||||||
|
string.IsNullOrEmpty(password)
|
||||||
|
|| string.IsNullOrEmpty(hashedPass)
|
||||||
|
|| !VerifyPassword(password, hashedPass)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
throw new Exception("Invalid Username or Password");
|
||||||
|
}
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GenerateToken(string user)
|
||||||
|
{
|
||||||
|
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
|
||||||
|
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
||||||
|
|
||||||
|
var token = new JwtSecurityToken(
|
||||||
|
issuer: "TimeLogServer",
|
||||||
|
audience: "TimeLogWebsite",
|
||||||
|
claims: [new Claim("user", user)],
|
||||||
|
expires: DateTime.Now.AddHours(2),
|
||||||
|
signingCredentials: creds
|
||||||
|
);
|
||||||
|
|
||||||
|
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool VerifyPassword(string enteredPassword, string storedHash)
|
||||||
|
{
|
||||||
|
byte[] hashBytes = Convert.FromBase64String(storedHash);
|
||||||
|
|
||||||
|
byte[] salt = new byte[16];
|
||||||
|
Array.Copy(hashBytes, 0, salt, 0, 16);
|
||||||
|
|
||||||
|
using var pbkdf2 = new Rfc2898DeriveBytes(
|
||||||
|
enteredPassword,
|
||||||
|
salt,
|
||||||
|
10000,
|
||||||
|
HashAlgorithmName.SHA256
|
||||||
|
);
|
||||||
|
byte[] newHash = pbkdf2.GetBytes(32);
|
||||||
|
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
if (newHash[i] != hashBytes[i + 16])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
// create server
|
||||||
|
HttpListener listener = new();
|
||||||
|
// routes need to be added first
|
||||||
|
listener.Prefixes.Add("http://localhost:5000/api/login/");
|
||||||
|
listener.Prefixes.Add("http://localhost:5000/api/register/");
|
||||||
|
listener.Prefixes.Add("http://localhost:5000/api/posts/");
|
||||||
|
listener.Prefixes.Add("http://localhost:5000/api/posts/like/");
|
||||||
|
listener.Prefixes.Add("http://localhost:5000/api/posts/unlike/");
|
||||||
|
listener.Prefixes.Add("http://localhost:5000/api/comment/");
|
||||||
|
listener.Prefixes.Add("http://localhost:5000/api/profile/");
|
||||||
|
listener.Prefixes.Add("http://localhost:5000/api/profile/experience/");
|
||||||
|
listener.Prefixes.Add("http://localhost:5000/api/profile/education/");
|
||||||
|
// listen
|
||||||
|
listener.Start();
|
||||||
|
Console.WriteLine("Server is listening on http://localhost:5000/");
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
HttpListenerContext context = listener.GetContext();
|
||||||
|
HttpListenerRequest request = context.Request;
|
||||||
|
HttpListenerResponse response = context.Response;
|
||||||
|
response.Headers.Add("Access-Control-Allow-Origin", "http://localhost:5173");
|
||||||
|
response.Headers.Add("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
||||||
|
response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||||
|
|
||||||
|
// url after localhost:5000/
|
||||||
|
string uri;
|
||||||
|
if (request != null && request.Url != null)
|
||||||
|
uri = request.Url.AbsolutePath;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
switch (request.HttpMethod)
|
||||||
|
{
|
||||||
|
case "GET":
|
||||||
|
HandleGet(uri, request, response);
|
||||||
|
break;
|
||||||
|
case "POST":
|
||||||
|
HandlePost(uri, request, response);
|
||||||
|
break;
|
||||||
|
case "DELETE":
|
||||||
|
HandleDelete(uri, request, response);
|
||||||
|
break;
|
||||||
|
case "PUT":
|
||||||
|
HandlePut(uri, request, response);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
HandleMissingPath(response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandlePut(
|
||||||
|
string uri,
|
||||||
|
HttpListenerRequest request,
|
||||||
|
HttpListenerResponse response
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (request.HasEntityBody)
|
||||||
|
switch (uri)
|
||||||
|
{
|
||||||
|
case "/api/profile":
|
||||||
|
UpdateProfile.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/education":
|
||||||
|
UpdateEducation.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/experience":
|
||||||
|
UpdateExperience.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/post":
|
||||||
|
UpdatePost.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/comment":
|
||||||
|
UpdateComment.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/posts/like":
|
||||||
|
UpdatePost.HandleLikes(request, response);
|
||||||
|
break;
|
||||||
|
// case "/api/posts/unlike":
|
||||||
|
// RemoveLike.HandleRequest(request, response);
|
||||||
|
// break;
|
||||||
|
default:
|
||||||
|
HandleMissingPath(response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HandleMissingPath(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleDelete(
|
||||||
|
string uri,
|
||||||
|
HttpListenerRequest request,
|
||||||
|
HttpListenerResponse response
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (request.HasEntityBody)
|
||||||
|
switch (uri)
|
||||||
|
{
|
||||||
|
case "/api/profile":
|
||||||
|
DeleteProfile.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/profile/education":
|
||||||
|
DeleteEducation.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/profile/experience":
|
||||||
|
DeleteExperience.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/posts":
|
||||||
|
DeletePost.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/comment":
|
||||||
|
DeleteComment.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
HandleMissingPath(response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HandleMissingPath(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandlePost(
|
||||||
|
string uri,
|
||||||
|
HttpListenerRequest request,
|
||||||
|
HttpListenerResponse response
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (request.HasEntityBody)
|
||||||
|
switch (uri)
|
||||||
|
{
|
||||||
|
case "/api/profile":
|
||||||
|
CreateProfile.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/profile/education":
|
||||||
|
CreateEducation.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/profile/experience":
|
||||||
|
CreateExperience.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/posts":
|
||||||
|
CreatePost.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/comment":
|
||||||
|
CreateComment.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/register":
|
||||||
|
Register.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
case "/api/login":
|
||||||
|
Login.HandleRequest(request, response);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
HandleMissingPath(response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HandleMissingPath(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleGet(
|
||||||
|
string uri,
|
||||||
|
HttpListenerRequest request,
|
||||||
|
HttpListenerResponse response
|
||||||
|
)
|
||||||
|
{
|
||||||
|
switch (uri)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
HandleMissingPath(response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleMissingPath(HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
response.StatusCode = 404;
|
||||||
|
string errorMessage = "Not Found";
|
||||||
|
byte[] buffer = Encoding.UTF8.GetBytes(errorMessage);
|
||||||
|
response.ContentType = "text/plain";
|
||||||
|
response.ContentLength64 = buffer.Length;
|
||||||
|
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||||
|
response.OutputStream.Write(buffer, 0, buffer.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
using System.Net;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class Register : SecuredRoute
|
||||||
|
{
|
||||||
|
private static void ValidateParams(Dictionary<string, string> paramsToValidate)
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
string.IsNullOrEmpty(paramsToValidate["username"])
|
||||||
|
|| paramsToValidate["username"].Length > 30
|
||||||
|
|| paramsToValidate["username"].Length < 4
|
||||||
|
|| string.IsNullOrEmpty(paramsToValidate["email"])
|
||||||
|
|| paramsToValidate["email"].Length > 50
|
||||||
|
|| paramsToValidate["email"].Length < 6
|
||||||
|
|| string.IsNullOrEmpty(paramsToValidate["password"])
|
||||||
|
|| paramsToValidate["password"].Length > 50
|
||||||
|
|| paramsToValidate["password"].Length < 10
|
||||||
|
)
|
||||||
|
{
|
||||||
|
throw new Exception("Wrong parameters");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<string> bodyParamNames = ["username", "email", "password"];
|
||||||
|
var bodyParamValues = ExtractBody(request, bodyParamNames);
|
||||||
|
ValidateParams(bodyParamValues);
|
||||||
|
|
||||||
|
MySqlCommand cmd = new(CreateInsertQuery("user", bodyParamNames));
|
||||||
|
bodyParamValues["password"] = HashPassword(bodyParamValues["password"]);
|
||||||
|
cmd = AddValuesToCmd(bodyParamValues, cmd);
|
||||||
|
using MySqlConnection conn = new(connectionString);
|
||||||
|
conn.Open();
|
||||||
|
cmd.Connection = conn;
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string HashPassword(string password)
|
||||||
|
{
|
||||||
|
byte[] salt = new byte[16];
|
||||||
|
RandomNumberGenerator.Fill(salt);
|
||||||
|
|
||||||
|
using var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000, HashAlgorithmName.SHA256);
|
||||||
|
byte[] hash = pbkdf2.GetBytes(32);
|
||||||
|
|
||||||
|
byte[] hashBytes = new byte[48]; // 16 (salt) + 32 (hash)
|
||||||
|
Array.Copy(salt, 0, hashBytes, 0, 16);
|
||||||
|
Array.Copy(hash, 0, hashBytes, 16, 32);
|
||||||
|
|
||||||
|
return Convert.ToBase64String(hashBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public abstract class Route
|
||||||
|
{
|
||||||
|
public static readonly string connectionString =
|
||||||
|
"server=127.0.0.1;uid=monty;pwd=some_pass;database=devcon";
|
||||||
|
|
||||||
|
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 static bool ValidateDate(string date)
|
||||||
|
{
|
||||||
|
Regex regex = new(@"^\d{4}-\d{2}-\d{2}$");
|
||||||
|
return regex.IsMatch(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static Dictionary<string, string> ExtractBody(
|
||||||
|
HttpListenerRequest request,
|
||||||
|
List<string> allowedParams
|
||||||
|
)
|
||||||
|
{
|
||||||
|
using StreamReader bodyReader = new(request.InputStream, request.ContentEncoding);
|
||||||
|
JObject bodyJO = JObject.Parse(bodyReader.ReadToEnd());
|
||||||
|
|
||||||
|
Dictionary<string, string> bodyParamValues = [];
|
||||||
|
foreach (var prop in bodyJO.Properties())
|
||||||
|
{
|
||||||
|
if (allowedParams.Contains(prop.Name))
|
||||||
|
bodyParamValues[prop.Name] = prop.Value.ToString();
|
||||||
|
}
|
||||||
|
return bodyParamValues;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class SecuredRoute : Route
|
||||||
|
{
|
||||||
|
protected static readonly string secretKey =
|
||||||
|
"stronk-key-much-sercret-much-more-stronk-stronk-key-much-sercret-much-more-stronk";
|
||||||
|
protected delegate void DelegateValidate(Dictionary<string, string> bodyparamValues);
|
||||||
|
|
||||||
|
protected static string ExtractUserId(HttpListenerRequest request)
|
||||||
|
{
|
||||||
|
var headers = request.Headers;
|
||||||
|
string token = headers["token"] ?? "";
|
||||||
|
string? usernameClaim = GetUserFromToken(token);
|
||||||
|
if (
|
||||||
|
!string.IsNullOrEmpty(token)
|
||||||
|
&& !ValidateToken(token)
|
||||||
|
&& string.IsNullOrEmpty(usernameClaim)
|
||||||
|
)
|
||||||
|
return "";
|
||||||
|
else
|
||||||
|
return usernameClaim;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static MySqlCommand AddValuesToCmd(
|
||||||
|
Dictionary<string, string> values,
|
||||||
|
MySqlCommand cmd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
foreach (var item in values)
|
||||||
|
{
|
||||||
|
cmd.Parameters.AddWithValue("@" + item.Key, item.Value);
|
||||||
|
}
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create an insert route and move this func there
|
||||||
|
protected static string CreateInsertQuery(string table, List<string> valuesToAdd)
|
||||||
|
{
|
||||||
|
string query =
|
||||||
|
"INSERT INTO "
|
||||||
|
+ table
|
||||||
|
+ "("
|
||||||
|
+ string.Join(",", valuesToAdd)
|
||||||
|
+ ") VALUES(@"
|
||||||
|
+ string.Join(",@", valuesToAdd)
|
||||||
|
+ ");";
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.3.0" />
|
||||||
|
<PackageReference Include="MySql.Data" Version="9.1.0" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.3.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
GET api/auth/ -- get token
|
||||||
|
GET api/posts
|
||||||
|
GET api/posts/:id
|
||||||
|
GET api/profile/me
|
||||||
|
GET api/profile/user/:user_id
|
||||||
|
GET api/profile/github/:username
|
||||||
|
# PUT api/profile/experience
|
||||||
|
# PUT api/profile/education
|
||||||
|
# PUT api/posts/like/:id
|
||||||
|
# PUT api/posts/unlike/:id
|
||||||
|
POST api/users -- register user
|
||||||
|
POST api/auth/ -- login
|
||||||
|
# POST api/profile
|
||||||
|
# POST api/posts
|
||||||
|
# POST api/posts/comment/:id
|
||||||
|
DELETE api/profile -- delete everything the user has done
|
||||||
|
# DELETE api/profile/education/:exp_id
|
||||||
|
# DELETE api/posts/comment/:id/:comment_id
|
||||||
|
# DELETE api/profile/experience/:exp_id
|
||||||
|
# DELETE api/posts/:id
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class UpdateComment : UpdateRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<string> validParamNames = ["message", "post", "id"];
|
||||||
|
|
||||||
|
UpdateDb(request, "comment", validParamNames, true);
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LikeComment(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
List<string> validParamNames = ["likes", "id"];
|
||||||
|
|
||||||
|
UpdateDb(request, "comment", validParamNames, true);
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class UpdateEducation : UpdateRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
List<string> validParamNames =
|
||||||
|
[
|
||||||
|
"school",
|
||||||
|
"degree",
|
||||||
|
"field",
|
||||||
|
"from_date",
|
||||||
|
"to_date",
|
||||||
|
"description",
|
||||||
|
"id",
|
||||||
|
];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UpdateDb(request, "education", validParamNames, true);
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class UpdateExperience : UpdateRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
List<string> validParamNames =
|
||||||
|
[
|
||||||
|
"job",
|
||||||
|
"company",
|
||||||
|
"location",
|
||||||
|
"from_date",
|
||||||
|
"to_date",
|
||||||
|
"description",
|
||||||
|
"id",
|
||||||
|
];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UpdateDb(request, "experience", validParamNames, true);
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class UpdateLikes : UpdateRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
List<string> validParamNames = ["id"];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UpdateLikes(request, "post", validParamNames, true);
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class UpdatePost : UpdateRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
List<string> validParamNames =
|
||||||
|
[
|
||||||
|
"f_name",
|
||||||
|
"l_name",
|
||||||
|
"company",
|
||||||
|
"website",
|
||||||
|
"location",
|
||||||
|
"github",
|
||||||
|
"status",
|
||||||
|
"bio",
|
||||||
|
"skills",
|
||||||
|
"twitter",
|
||||||
|
"facebook",
|
||||||
|
"youtube",
|
||||||
|
"linkedin",
|
||||||
|
"instagram",
|
||||||
|
"id",
|
||||||
|
];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UpdateDb(request, "post", validParamNames, true);
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HandleLikes(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
List<string> validParamNames = ["id"];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UpdateLikes(request, "post", validParamNames, true);
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class UpdateProfile : UpdateRoute
|
||||||
|
{
|
||||||
|
public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
|
||||||
|
{
|
||||||
|
List<string> validParamNames =
|
||||||
|
[
|
||||||
|
"f_name",
|
||||||
|
"l_name",
|
||||||
|
"company",
|
||||||
|
"website",
|
||||||
|
"location",
|
||||||
|
"github",
|
||||||
|
"status",
|
||||||
|
"bio",
|
||||||
|
"skills",
|
||||||
|
"twitter",
|
||||||
|
"facebook",
|
||||||
|
"youtube",
|
||||||
|
"linkedin",
|
||||||
|
"instagram",
|
||||||
|
];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UpdateDb(request, "profile", validParamNames, false);
|
||||||
|
SendSuccess(response);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SendError(response, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
using System.Net;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
|
||||||
|
namespace Server;
|
||||||
|
|
||||||
|
public class UpdateRoute : SecuredRoute
|
||||||
|
{
|
||||||
|
//TODO create editied time on field in db for comments and posts
|
||||||
|
//TODO all updates need validation and deletes
|
||||||
|
protected static void UpdateDb(
|
||||||
|
HttpListenerRequest request,
|
||||||
|
string table,
|
||||||
|
List<string> validParamNames,
|
||||||
|
bool requireId
|
||||||
|
)
|
||||||
|
{
|
||||||
|
string user_id = ExtractUserId(request);
|
||||||
|
var bodyParamValues = ExtractBody(request, validParamNames);
|
||||||
|
|
||||||
|
if (requireId && bodyParamValues["id"] is null)
|
||||||
|
throw new Exception("missing id");
|
||||||
|
|
||||||
|
string temp = "";
|
||||||
|
foreach (var item in bodyParamValues)
|
||||||
|
{
|
||||||
|
temp += item.Key + "=\"" + item.Value + "\",";
|
||||||
|
}
|
||||||
|
// remove last chat from str
|
||||||
|
temp = temp[..^1];
|
||||||
|
|
||||||
|
validParamNames.Add("user_id");
|
||||||
|
bodyParamValues["user_id"] = user_id;
|
||||||
|
|
||||||
|
temp += requireId ? " WHERE user_id=@user_id AND id=@id;" : " WHERE user_id=@user_id;";
|
||||||
|
|
||||||
|
MySqlCommand cmd = new("UPDATE " + table + " SET " + temp);
|
||||||
|
cmd = AddValuesToCmd(bodyParamValues, cmd);
|
||||||
|
|
||||||
|
using MySqlConnection conn = new(connectionString);
|
||||||
|
conn.Open();
|
||||||
|
cmd.Connection = conn;
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void UpdateLikes(
|
||||||
|
HttpListenerRequest request,
|
||||||
|
string table,
|
||||||
|
List<string> validParamNames,
|
||||||
|
bool requireId
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var bodyParamValues = ExtractBody(request, validParamNames);
|
||||||
|
if (requireId && bodyParamValues["id"] is null)
|
||||||
|
throw new Exception("missing id");
|
||||||
|
|
||||||
|
string query = "SELECT likes from post Where id=@id;";
|
||||||
|
MySqlCommand cmd2 = new(query);
|
||||||
|
using MySqlConnection conn = new(connectionString);
|
||||||
|
cmd2.Connection = conn;
|
||||||
|
conn.Open();
|
||||||
|
cmd2.Parameters.AddWithValue("@id", bodyParamValues["id"]);
|
||||||
|
MySqlDataReader reader = cmd2.ExecuteReader();
|
||||||
|
string? id = "";
|
||||||
|
string? likes = "";
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
id = Convert.ToString(reader["id"]);
|
||||||
|
likes = Convert.ToString(reader["likes"]);
|
||||||
|
}
|
||||||
|
Console.WriteLine(id);
|
||||||
|
|
||||||
|
query = "Update post SET likes=2 where id=1;";
|
||||||
|
MySqlCommand cmd = new(query);
|
||||||
|
cmd = AddValuesToCmd(bodyParamValues, cmd);
|
||||||
|
|
||||||
|
cmd.Connection = conn;
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
# register
|
||||||
|
curl -X POST localhost:5000/api/register
|
||||||
|
-d
|
||||||
|
{
|
||||||
|
"username":"tombo" ,
|
||||||
|
"password":"1234567890" ,
|
||||||
|
"email":"temp@mail.com"
|
||||||
|
}
|
||||||
|
# login
|
||||||
|
curl -X POST localhost:5000/api/login
|
||||||
|
-d
|
||||||
|
{
|
||||||
|
"password":"1234567890" ,
|
||||||
|
"email":"temp@mail.com"
|
||||||
|
}
|
||||||
|
# add profile
|
||||||
|
curl -X POST localhost:5000/api/profile
|
||||||
|
-H "token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiMSIsImV4cCI6MTczNDEyOTM5MSwiaXNzIjoiVGltZUxvZ1NlcnZlciIsImF1ZCI6IlRpbWVMb2dXZWJzaXRlIn0.TZQQUaMBhL3PO3BvwpANMCImCk_RxGg7B5rTcbs9gRg"
|
||||||
|
-d
|
||||||
|
{
|
||||||
|
"f_name":"somef_name" ,
|
||||||
|
"l_name":"somel_name" ,
|
||||||
|
"company":"somecompany" ,
|
||||||
|
"website":"somewebsite" ,
|
||||||
|
"location":"somelocation" ,
|
||||||
|
"skills":"someskills" ,
|
||||||
|
"github":"somegithub" ,
|
||||||
|
"status":"somestatus" ,
|
||||||
|
"bio":"somebio" ,
|
||||||
|
"twitter":"sometwitter" ,
|
||||||
|
"youtube":"someyoutube" ,
|
||||||
|
"facebook":"somefacebook" ,
|
||||||
|
"linkedin":"somelinkedi" ,
|
||||||
|
"instagram":"someinstagram"
|
||||||
|
}
|
||||||
|
|
||||||
|
#update profile
|
||||||
|
curl -X PUT localhost:5000/api/profile/update
|
||||||
|
-H "token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiMSIsImV4cCI6MTczNDEyOTM5MSwiaXNzIjoiVGltZUxvZ1NlcnZlciIsImF1ZCI6IlRpbWVMb2dXZWJzaXRlIn0.TZQQUaMBhL3PO3BvwpANMCImCk_RxGg7B5rTcbs9gRg"
|
||||||
|
-d
|
||||||
|
{
|
||||||
|
"f_name":"Rombo" ,
|
||||||
|
"l_name":"Tombo" ,
|
||||||
|
"website":"TOMBOBOBOBO"
|
||||||
|
}
|
||||||
|
# "company":"somecompany" ,
|
||||||
|
# "website":"somewebsite" ,
|
||||||
|
# "location":"somelocation" ,
|
||||||
|
# "skills":"someskills" ,
|
||||||
|
# "github":"somegithub" ,
|
||||||
|
# "status":"somestatus" ,
|
||||||
|
# "bio":"somebio" ,
|
||||||
|
# "twitter":"sometwitter" ,
|
||||||
|
# "youtube":"someyoutube" ,
|
||||||
|
# "facebook":"somefacebook" ,
|
||||||
|
# "linkedin":"somelinkedi" ,
|
||||||
|
# "instagram":"someinstagram"
|
||||||
|
# }
|
||||||
|
|
||||||
|
# add education
|
||||||
|
curl -X POST localhost:5000/api/profile/education
|
||||||
|
-H "token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiMSIsImV4cCI6MTczNDEyOTM5MSwiaXNzIjoiVGltZUxvZ1NlcnZlciIsImF1ZCI6IlRpbWVMb2dXZWJzaXRlIn0.TZQQUaMBhL3PO3BvwpANMCImCk_RxGg7B5rTcbs9gRg"
|
||||||
|
-d
|
||||||
|
{
|
||||||
|
"school": "someschool" ,
|
||||||
|
"degree": "somedegree" ,
|
||||||
|
"field": "somefield" ,
|
||||||
|
"from_date": "2020-01-01" ,
|
||||||
|
"to_date": "2020-02-02" ,
|
||||||
|
"description": "somedescription"
|
||||||
|
}
|
||||||
|
#update education
|
||||||
|
curl -X PUT localhost:5000/api/profile/education
|
||||||
|
-H "token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiMSIsImV4cCI6MTczNDEyOTM5MSwiaXNzIjoiVGltZUxvZ1NlcnZlciIsImF1ZCI6IlRpbWVMb2dXZWJzaXRlIn0.TZQQUaMBhL3PO3BvwpANMCImCk_RxGg7B5rTcbs9gRg"
|
||||||
|
-d
|
||||||
|
{
|
||||||
|
"school": "TOOBOBOOB" ,
|
||||||
|
"degree": "somedegree" ,
|
||||||
|
"field": "somefield" ,
|
||||||
|
"from_date": "2020-01-01" ,
|
||||||
|
"to_date": "2020-02-02" ,
|
||||||
|
"description": "somedescription",
|
||||||
|
"id":"1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# add exp
|
||||||
|
curl -X POST localhost:5000/api/profile/experience
|
||||||
|
-H "token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiMSIsImV4cCI6MTczNDEyOTM5MSwiaXNzIjoiVGltZUxvZ1NlcnZlciIsImF1ZCI6IlRpbWVMb2dXZWJzaXRlIn0.TZQQUaMBhL3PO3BvwpANMCImCk_RxGg7B5rTcbs9gRg"
|
||||||
|
-d
|
||||||
|
{
|
||||||
|
"job":"somejob" ,
|
||||||
|
"company":"somecompany" ,
|
||||||
|
"location":"somelocation" ,
|
||||||
|
"from_date":"2020-01-01" ,
|
||||||
|
"to_date":"2020-02-02" ,
|
||||||
|
"description":"12312312312312312312"
|
||||||
|
}
|
||||||
|
|
||||||
|
# add post
|
||||||
|
curl -X POST localhost:5000/api/post
|
||||||
|
-H "token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiMSIsImV4cCI6MTczNDEyOTM5MSwiaXNzIjoiVGltZUxvZ1NlcnZlciIsImF1ZCI6IlRpbWVMb2dXZWJzaXRlIn0.TZQQUaMBhL3PO3BvwpANMCImCk_RxGg7B5rTcbs9gRg"
|
||||||
|
-d
|
||||||
|
{
|
||||||
|
"message":"lskadfjalsk;djf;laksdjf;lsa"
|
||||||
|
}
|
||||||
|
#update profile
|
||||||
|
curl -X PUT localhost:5000/api/post/like
|
||||||
|
-H "token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiMSIsImV4cCI6MTczNDEyOTM5MSwiaXNzIjoiVGltZUxvZ1NlcnZlciIsImF1ZCI6IlRpbWVMb2dXZWJzaXRlIn0.TZQQUaMBhL3PO3BvwpANMCImCk_RxGg7B5rTcbs9gRg"
|
||||||
|
-d
|
||||||
|
{
|
||||||
|
"id":"4"
|
||||||
|
}
|
||||||
|
|
||||||
|
# add comment
|
||||||
|
curl -X POST localhost:5000/api/comment
|
||||||
|
-H "token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiMSIsImV4cCI6MTczNDEyOTM5MSwiaXNzIjoiVGltZUxvZ1NlcnZlciIsImF1ZCI6IlRpbWVMb2dXZWJzaXRlIn0.TZQQUaMBhL3PO3BvwpANMCImCk_RxGg7B5rTcbs9gRg"
|
||||||
|
-d
|
||||||
|
{
|
||||||
|
"message":"lskadfjalsk;djf;laksdjf;lsa" ,
|
||||||
|
"post":"1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# remove comment
|
||||||
|
curl -X DELETE localhost:5000/api/comment
|
||||||
|
-H "token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiMSIsImV4cCI6MTczNDEyOTM5MSwiaXNzIjoiVGltZUxvZ1NlcnZlciIsImF1ZCI6IlRpbWVMb2dXZWJzaXRlIn0.TZQQUaMBhL3PO3BvwpANMCImCk_RxGg7B5rTcbs9gRg"
|
||||||
|
-d
|
||||||
|
{
|
||||||
|
"id":"2"
|
||||||
|
}
|
||||||
|
|
||||||
|
# remove education
|
||||||
|
curl -X DELETE localhost:5000/api/profile/education
|
||||||
|
-H "token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiMSIsImV4cCI6MTczNDEyOTM5MSwiaXNzIjoiVGltZUxvZ1NlcnZlciIsImF1ZCI6IlRpbWVMb2dXZWJzaXRlIn0.TZQQUaMBhL3PO3BvwpANMCImCk_RxGg7B5rTcbs9gRg"
|
||||||
|
-d
|
||||||
|
{
|
||||||
|
"id":"2"
|
||||||
|
}
|
||||||
|
|
||||||
|
# remove experience
|
||||||
|
curl -X DELETE localhost:5000/api/profile/experience
|
||||||
|
-H "token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiMSIsImV4cCI6MTczNDEyOTM5MSwiaXNzIjoiVGltZUxvZ1NlcnZlciIsImF1ZCI6IlRpbWVMb2dXZWJzaXRlIn0.TZQQUaMBhL3PO3BvwpANMCImCk_RxGg7B5rTcbs9gRg"
|
||||||
|
-d
|
||||||
|
{
|
||||||
|
"id":"2"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user