Merge pull request 'intial-blog-setup' (#33) from intial-blog-setup into master

Reviewed-on: #33
This commit is contained in:
Rohit Pai 2023-06-09 14:56:34 +01:00
commit 88c5cc9508
49 changed files with 1659 additions and 1033 deletions

4
.gitignore vendored
View File

@ -75,6 +75,6 @@ fabric.properties
.env .env
vendor/* vendor/*
node_modules/* node_modules/*
src/api/config.php src/api/utils/config.php
dist/api/config.php dist/api/utils/config.php
dist/api/.htaccess dist/api/.htaccess

BIN
blog main page.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 752 KiB

BIN
blog post.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 KiB

97
dist/api/blog/blogData.php vendored Normal file
View File

@ -0,0 +1,97 @@
<?php
namespace api\blog;
use PDO;
require_once __DIR__ . "/../utils/config.php";
/**
* Blog Data Class
* Define all functions which either get, update, create or delete posts
*/
class blogData
{
/**
* Get all blog posts
* @return array - Array of all blog posts or error message
*/
function getBlogPosts(): array
{
$conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, body, tags FROM blog ORDER BY dateCreated DESC;");
$stmt->execute();
// set the resulting array to associative
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
if ($result)
{
return $result;
}
return array("errorMessage" => "Error, blog data not found");
}
/**
* Get a blog post with the given ID
* @param string $ID - ID of the blog post to get
* @return array - Array of all blog posts or error message
*/
function getBlogPost(string $ID): array
{
$conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, tags FROM blog WHERE ID = :ID;");
$stmt->bindParam(":ID", $ID);
$stmt->execute();
// set the resulting array to associative
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result)
{
return $result;
}
return array("errorMessage" => "Error, blog post could not found");
}
/**
* Get the latest blog post
* @return array - Array of the latest blog post or error message
*/
function getLatestBlogPost(): array
{
$conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, tags FROM blog ORDER BY dateCreated DESC LIMIT 1;");
$stmt->execute();
// set the resulting array to associative
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result)
{
return $result;
}
return array("errorMessage" => "Error, blog post could not found");
}
/**
* Get featured blog post
* @return array - Array of the featured blog post or error message
*/
function getFeaturedBlogPost(): array
{
$conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, tags FROM blog WHERE featured = 1;");
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result)
{
return $result;
}
return array("errorMessage" => "Error, blog post could not found");
}
}

35
dist/api/blog/blogRoutes.php vendored Normal file
View File

@ -0,0 +1,35 @@
<?php
namespace api\blog;
require_once __DIR__ . "/../utils/routesInterface.php";
require_once "blogData.php";
use api\utils\routesInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;
class blogRoutes implements routesInterface
{
private blogData $blogData;
/**
* constructor used to instantiate a base blog routes, to be used in the index.php file.
* @param App $app - the slim app used to create the routes
*/
public function __construct(App $app)
{
$this->blogData = new blogData();
$this->createRoutes($app);
}
/**
* creates the routes for the blog
* @param App $app - the slim app used to create the routes
* @return void - returns nothing
*/
public function createRoutes(App $app): void
{
// TODO: Implement createRoutes() method.
}
}

481
dist/api/index.php vendored
View File

@ -1,26 +1,25 @@
<?php /** @noinspection PhpIncludeInspection */ <?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
////////////////// Index file ////////////// ////////////////// Index file //////////////
/// Creates base routes and runs /// /// Creates base routes and runs ///
/// respective functions /// /// respective functions ///
//////////////////////////////////////////// ////////////////////////////////////////////
//require “routes.php”;
require "../vendor/autoload.php"; require "../vendor/autoload.php";
include "middleware.php"; require "utils/middleware.php";
include "timelineData.php"; require "timeline/timelineRoutes.php";
include "projectData.php"; require "project/projectRoutes.php";
include "user.php"; require "user/userRoutes.php";
require "blog/blogRoutes.php";
use api\middleware; use api\blog\blogRoutes;
use api\projectData; use api\project\projectRoutes;
use api\timelineData; use api\timeline\timelineRoutes;
use api\user; use api\user\userRoutes;
use api\utils\middleware;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Selective\SameSiteCookie\SameSiteCookieConfiguration;
use Selective\SameSiteCookie\SameSiteCookieMiddleware;
use Slim\Factory\AppFactory; use Slim\Factory\AppFactory;
use Tuupola\Middleware\JwtAuthentication;
// Start slim // Start slim
$app = AppFactory::create(); $app = AppFactory::create();
@ -31,310 +30,26 @@ $app->setBasePath("/api");
// Add middleware // Add middleware
new middleware($app); new middleware($app);
$timelineData = new timelineData(); new timelineRoutes($app);
$projectData = new projectData(); new projectRoutes($app);
$user = new user(); new blogRoutes($app);
new userRoutes($app);
$app->get("/timelineData/{timeline}", function (Request $request, Response $response, array $args)
{
global $timelineData;
//check if route is available if it is get the data
//otherwise return an error
if($args["timeline"] == "edu")
{
$response->getBody()->write(json_encode($timelineData->getEduData()));
return $response;
}
if($args["timeline"] == "work")
{
$response->getBody()->write(json_encode($timelineData->getWorkData()));
return $response;
}
// something went wrong
$response->getBody()->write(json_encode(array("errorMessage" => "Error, timeline data not found")));
return $response->withStatus(404);
});
$app->patch("/timelineData/{timeline}/{id}", function (Request $request, Response $response, array $args)
{
global $timelineData;
$data = $request->getParsedBody();
if ($args["timeline"] == "edu" && $args["id"] != "undefined")
{
if (empty($data["dateFrom"]) || empty($data["dateTo"]) || empty($data["grade"]) || empty($data["course"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
if (!$timelineData->updateEduData($data["dateFrom"], $data["dateTo"], $data["grade"], $data["course"], $args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->withStatus(201);
return $response;
}
if ($args["timeline"] == "work" && $args["id"] != "undefined")
{
if (empty($data["dateFrom"]) || empty($data["dateTo"]) || empty($data["companyName"]) || empty($data["area"]) || empty($data["title"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
if (!$timelineData->updateWorkData($data["dateFrom"], $data["dateTo"], $data["companyName"], $data["area"], $data["title"], $args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->withStatus(201);
return $response;
}
$response->getBody()->write(json_encode(array("error" => "The correct data was not sent")));
return $response->withStatus(400);
});
$app->delete("/timelineData/{timeline}/{id}", function (Request $request, Response $response, array $args)
{
global $timelineData;
if ($args["timeline"] == "edu" && $args["id"] != null)
{
if (!$timelineData->deleteEduData($args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
return $response;
}
if ($args["timeline"] == "work" && $args["id"] != null)
{
if (!$timelineData->deleteWorkData($args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
return $response;
}
$response->getBody()->write(json_encode(array("error" => "The correct data was not sent")));
return $response->withStatus(400);
});
$app->post("/timelineData/{timeline}", function (Request $request, Response $response, array $args)
{
global $timelineData;
$data = $request->getParsedBody();
if ($args["timeline"] == "edu")
{
if (empty($data["dateFrom"]) || empty($data["dateTo"]) || empty($data["grade"]) || empty($data["course"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$insertedID = $timelineData->addEduData($data["dateFrom"], $data["dateTo"], $data["grade"], $data["course"]);
if (!is_int($insertedID))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode(array("ID" => $insertedID)));
$response->withStatus(201);
return $response;
}
if ($args["timeline"] == "work")
{
if (empty($data["dateFrom"]) || empty($data["companyName"]) || empty($data["area"]) || empty($data["title"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
if (empty($data["dateTo"]))
{
$data["dateTo"] = "";
}
$insertedID = $timelineData->addWorkData($data["dateFrom"], $data["dateTo"], $data["companyName"], $data["area"], $data["title"]);
if (!is_int($insertedID))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode(array("ID" => $insertedID)));
$response->withStatus(201);
return $response;
}
$response->getBody()->write(json_encode(array("error" => "The correct data was not sent")));
return $response->withStatus(400);
});
$app->get("/projectData", function (Request $request, Response $response)
{
global $projectData;
$result = $projectData->getProjectData();
$json = json_encode($result);
$response->getBody()->write($json);
if(array_key_exists("errorMessage", $result))
{
$response = $response->withStatus(404);
}
//use content type json to indicate json data on frontend.
return $response;
});
$app->patch("/projectData/{id}", function (Request $request, Response $response, array $args)
{
global $projectData;
$data = $request->getParsedBody();
if ($args["id"] != "undefined")
{
if (empty($data["title"]) || empty($data["isMainProject"]) || empty($data["information"]) || empty($data["gitLink"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$update = $projectData->updateProjectData($args["id"], $data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["gitLink"]);
if ($update === "unset main project")
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Can't unset project as main project, try updating another project as the main project")));
return $response->withStatus(400);
}
if (!$update)
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
return $response;
}
$response->getBody()->write(json_encode(array("error" => "Please provide an ID")));
return $response->withStatus(400);
});
$app->delete("/projectData/{id}", function (Request $request, Response $response, array $args)
{
global $projectData;
if ($args["id"] != null)
{
$message = $projectData->deleteProjectData($args["id"]);
if ($message === "error")
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong or the project with ID ".$args["id"]."does not exist")));
return $response->withStatus(500);
}
if ($message === "cannot delete")
{
//uh oh cannot delete the main project
$response->getBody()->write(json_encode(array("error" => "Cannot delete the main project")));
return $response->withStatus(409);
}
return $response;
}
$response->getBody()->write(json_encode(array("error" => "Please provide an ID")));
return $response->withStatus(400);
});
$app->post("/projectData", function (Request $request, Response $response)
{
global $projectData;
$data = $request->getParsedBody();
if (empty($data["title"]) || empty($data["isMainProject"]) || empty($data["information"]) || empty($data["gitLink"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$insertedID = $projectData->addProjectData($data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["gitLink"]);
if (!is_int($insertedID))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong", "message" => $insertedID)));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode(array("ID" => $insertedID)));
return $response;
});
$app->post("/projectImage/{id}", function (Request $request, Response $response, array $args)
{
global $projectData;
$files = $request->getUploadedFiles();
if (empty($args["id"]) || empty($files))
{
// uh oh only some of the data was sent
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$message = $projectData->uploadImage($args["id"], $files["img"]);
if (!is_array($message))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => $message)));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode($message));
return $response;
});
// misc routes
$app->post("/contact", function (Request $request, Response $response) $app->post("/contact", function (Request $request, Response $response)
{ {
$data = $request->getParsedBody(); $data = $request->getParsedBody();
if(empty($data["fName"]) || empty($data["lName"]) || empty($data["email"]) || empty($data["subject"]) || empty($data["message"])) if(empty($data["fName"]) || empty($data["lName"]) || empty($data["email"]) || empty($data["subject"]) || empty($data["message"]))
{ {
$response->getBody()->write(json_encode(array("errorMessage" => "Please fill out all the fields"))); $response->getBody()->write(json_encode(array("errorMessage" => "Please fill out all the fields")));
return $response->withStatus(400); return $response->withStatus(400);
} }
if (!filter_var($data["email"], FILTER_VALIDATE_EMAIL)) if (!filter_var($data["email"], FILTER_VALIDATE_EMAIL))
{ {
$response->getBody()->write(json_encode(array("errorMessage" => "Email is not the correct format"))); $response->getBody()->write(json_encode(array("errorMessage" => "Email is not the correct format")));
return $response->withStatus(400); return $response->withStatus(400);
} }
// email form filler/conatcter // email form filler/conatcter
@ -343,12 +58,12 @@ $app->post("/contact", function (Request $request, Response $response)
$headers1 .= "MIME-Version: 1.0\r\n"; $headers1 .= "MIME-Version: 1.0\r\n";
$headers1 .= "Content-Type: text/html; charset=UTF-8\r\n"; $headers1 .= "Content-Type: text/html; charset=UTF-8\r\n";
$message1 = " $message1 = <<<HEREA
<html lang=\"en\"> <html lang="en">
<head> <head>
<title>{$data['subject']}</title> <title>{$data['subject']}</title>
<style> <style>
@import url(\"https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400;1,700&family=Share+Tech+Mono&family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap\"); @import url("https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400;1,700&family=Share+Tech+Mono&family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap");
body { body {
font-family: Noto Sans KR, sans-serif; font-family: Noto Sans KR, sans-serif;
font-style: normal; font-style: normal;
@ -403,17 +118,17 @@ $app->post("/contact", function (Request $request, Response $response)
<tr> <tr>
<td>{$data['fName']}</td> <td>{$data['fName']}</td>
<td>{$data['lName']}</td> <td>{$data['lName']}</td>
<td><a href=\"mailto:{$data['email']}\">{$data['email']}</a></td> <td><a href="mailto:{$data['email']}">{$data['email']}</a></td>
<td>{$data['subject']}</td> <td>{$data['subject']}</td>
<td>{$data['message']}</td> <td>{$data['message']}</td>
</tr> </tr>
</table> </table>
<br> <br>
<hr> <hr>
<p>Regards, <br> Rohit Pai <br> <a href=\"mailto:rohit@rohitpai.co.uk\">rohit@rohitpai.co.uk</a> <p>Regards, <br> Rohit Pai <br> <a href="mailto:rohit@rohitpai.co.uk">rohit@rohitpai.co.uk</a>
</body> </body>
</html> </html>
"; HEREA;
mail($data["email"], $data["subject"], $message1, $headers1); mail($data["email"], $data["subject"], $message1, $headers1);
@ -423,12 +138,12 @@ $app->post("/contact", function (Request $request, Response $response)
$headers2 .= "MIME-Version: 1.0\r\n"; $headers2 .= "MIME-Version: 1.0\r\n";
$headers2 .= "Content-Type: text/html; charset=UTF-8\r\n"; $headers2 .= "Content-Type: text/html; charset=UTF-8\r\n";
$message2 = " $message2 = <<<HEREB
<html lang=\"en\"> <html lang="en">
<head> <head>
<title>{$data['subject']}</title> <title>{$data['subject']}</title>
<style> <style>
@import url(\"https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400;1,700&family=Share+Tech+Mono&family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap\"); @import url("https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400;1,700&family=Share+Tech+Mono&family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap");
body { body {
font-family: Noto Sans KR, sans-serif; font-family: Noto Sans KR, sans-serif;
font-style: normal; font-style: normal;
@ -481,147 +196,17 @@ $app->post("/contact", function (Request $request, Response $response)
<tr> <tr>
<td>{$data['fName']}</td> <td>{$data['fName']}</td>
<td>{$data['lName']}</td> <td>{$data['lName']}</td>
<td><a href=\"mailto:{$data['email']}\">{$data['email']}</a></td> <td><a href="mailto:{$data['email']}">{$data['email']}</a></td>
<td>{$data['subject']}</td> <td>{$data['subject']}</td>
<td>{$data['message']}</td> <td>{$data['message']}</td>
</tr> </tr>
</table> </table>
</body> </body>
</html> </html>
"; HEREB;
mail("rohit@rohitpai.co.uk", "{$data['fName']} {$data['lName']} filled in the form", $message2, $headers2); mail("rohit@rohitpai.co.uk", "{$data['fName']} {$data['lName']} filled in the form", $message2, $headers2);
return $response->withStatus(201); return $response->withStatus(201);
}); });
$app->post("/user/login", function (Request $request, Response $response)
{
global $user;
// get request data
$data = $request->getParsedBody();
if (empty($data["username"]) || empty($data["password"]))
{
// uh oh user sent empty data
return $response->withStatus(400);
}
if ($user->checkUser($data["username"], $data["password"]))
{
// yay, user is logged in
$_SESSION["token"] = $user->createToken($data["username"]);
$_SESSION["username"] = $data["username"];
$response->getBody()->write(json_encode(array("token" => $_SESSION["token"])));
return $response;
}
$response->getBody()->write(json_encode(array("error" => "Unauthorised")));
return $response->withStatus(401);
});
$app->get("/user/logout", function (Request $request, Response $response)
{
session_unset();
return $response;
});
$app->get("/user/isLoggedIn", function (Request $request, Response $response)
{
global $user;
if (empty($_SESSION["token"]) && empty($_SESSION["username"]))
{
// uh oh user not logged in
return $response->withStatus(401);
}
if (empty($_SESSION["token"]))
{
// user is logged in but no token was created
$_SESSION["token"] = $user->createToken($_SESSION["username"]);
return $response;
}
$response->getBody()->write(json_encode(array("token" => $_SESSION["token"])));
return $response;
});
$app->get("/user/checkResetEmail/{email}", function (Request $request, Response $response, array $args)
{
global $user;
if (empty($args["email"]))
{
// uh oh sent empty data
return $response->withStatus(400);
}
if ($user->checkEmail($args["email"]))
{
// yay email does exist
$_SESSION["resetToken"] = $user->sendResetEmail($args["email"]);
$_SESSION["resetEmail"] = $args["email"];
return $response;
}
return $response->withStatus(404);
});
$app->get("/user/resendEmail", function (Request $request, Response $response)
{
if (empty($_SESSION["resetToken"]))
{
// uh oh not authorized to resend email
return $response->withStatus(401);
}
global $user;
$_SESSION["resetToken"] = $user->sendResetEmail($_SESSION["resetEmail"]);
return $response;
});
$app->get("/user/checkResetCode/{code}", function (Request $request, Response $response, array $args)
{
if (empty($args["code"]))
{
// uh oh sent empty data
return $response->withStatus(400);
}
if ($_SESSION["resetToken"] === $args["code"])
{
// yay, code code matches
return $response;
}
return $response->withStatus(401);
});
$app->post("/user/changePassword", function (Request $request, Response $response)
{
global $user;
if (empty($_SESSION["resetToken"]) && empty($_SESSION["resetEmail"]))
{
// uh oh not authorized to change password
return $response->withStatus(401);
}
$data = $request->getParsedBody();
if (empty($data["password"]))
{
// uh oh sent empty data
return $response->withStatus(400);
}
if ($user->changePassword($_SESSION["resetEmail"], $data["password"]))
{
// yay, password changed
unset($_SESSION["resetToken"]);
unset($_SESSION["resetEmail"]);
return $response;
}
return $response->withStatus(500);
});
$app->run(); $app->run();

View File

@ -1,9 +1,9 @@
<?php <?php
namespace api; namespace api\project;
use PDO; use PDO;
use Psr\Http\Message\UploadedFileInterface; use Psr\Http\Message\UploadedFileInterface;
require_once "./config.php"; require_once __DIR__ . "/../utils/config.php";
/** /**
* Project Data Class * Project Data Class

153
dist/api/project/projectRoutes.php vendored Normal file
View File

@ -0,0 +1,153 @@
<?php
namespace api\project;
require_once __DIR__ . "/../utils/routesInterface.php";
require_once "projectData.php";
use api\utils\routesInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;
class projectRoutes implements routesInterface
{
private projectData $projectData;
/**
* constructor used to instantiate a base project routes, to be used in the index.php file.
* @param App $app - the slim app used to create the routes
*/
public function __construct(App $app)
{
$this->projectData = new projectData();
$this->createRoutes($app);
}
/**
* creates the routes for the project
* @param App $app - the slim app used to create the routes
* @return void - returns nothing
*/
public function createRoutes(App $app): void
{
$app->get("/projectData", function (Request $request, Response $response)
{
$result = $this->projectData->getProjectData();
$json = json_encode($result);
$response->getBody()->write($json);
if(array_key_exists("errorMessage", $result))
{
$response = $response->withStatus(404);
}
//use content type json to indicate json data on frontend.
return $response;
});
$app->patch("/projectData/{id}", function (Request $request, Response $response, array $args)
{
$data = $request->getParsedBody();
if ($args["id"] != "undefined")
{
if (empty($data["title"]) || empty($data["isMainProject"]) || empty($data["information"]) || empty($data["gitLink"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$update = $this->projectData->updateProjectData($args["id"], $data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["gitLink"]);
if ($update === "unset main project")
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Can't unset project as main project, try updating another project as the main project")));
return $response->withStatus(400);
}
if (!$update)
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
return $response;
}
$response->getBody()->write(json_encode(array("error" => "Please provide an ID")));
return $response->withStatus(400);
});
$app->delete("/projectData/{id}", function (Request $request, Response $response, array $args)
{
if ($args["id"] != null)
{
$message = $this->projectData->deleteProjectData($args["id"]);
if ($message === "error")
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong or the project with ID ".$args["id"]."does not exist")));
return $response->withStatus(500);
}
if ($message === "cannot delete")
{
//uh oh cannot delete the main project
$response->getBody()->write(json_encode(array("error" => "Cannot delete the main project")));
return $response->withStatus(409);
}
return $response;
}
$response->getBody()->write(json_encode(array("error" => "Please provide an ID")));
return $response->withStatus(400);
});
$app->post("/projectData", function (Request $request, Response $response)
{
$data = $request->getParsedBody();
if (empty($data["title"]) || empty($data["isMainProject"]) || empty($data["information"]) || empty($data["gitLink"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$insertedID = $this->projectData->addProjectData($data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["gitLink"]);
if (!is_int($insertedID))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong", "message" => $insertedID)));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode(array("ID" => $insertedID)));
return $response;
});
$app->post("/projectImage/{id}", function (Request $request, Response $response, array $args)
{
$files = $request->getUploadedFiles();
if (empty($args["id"]) || empty($files))
{
// uh oh only some of the data was sent
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$message = $this->projectData->uploadImage($args["id"], $files["img"]);
if (!is_array($message))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => $message)));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode($message));
return $response;
});
}
}

View File

@ -1,10 +1,10 @@
<?php <?php
namespace api; namespace api\timeline;
use PDO; use PDO;
require_once "./config.php"; require_once __DIR__ . "/../utils/config.php";
/** /**
* TimelineData class * TimelineData class

186
dist/api/timeline/timelineRoutes.php vendored Normal file
View File

@ -0,0 +1,186 @@
<?php
namespace api\timeline;
require_once __DIR__ . "/../utils/routesInterface.php";
require_once "timelineData.php";
use api\utils\routesInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;
class timelineRoutes implements routesInterface
{
private timelineData $timelineData;
/**
* constructor used to instantiate a base timeline routes, to be used in the index.php file.
* @param App $app - the slim app used to create the routes
*/
public function __construct(App $app)
{
$this->timelineData = new timelineData();
$this->createRoutes($app);
}
/**
* creates the routes for the timeline
* @param App $app - the slim app used to create the routes
* @return void - returns nothing
*/
public function createRoutes(App $app): void
{
$app->get("/timelineData/{timeline}", function (Request $request, Response $response, array $args)
{
//check if route is available if it is get the data
//otherwise return an error
if ($args["timeline"] == "edu")
{
$response->getBody()->write(json_encode($this->timelineData->getEduData()));
return $response;
}
if($args["timeline"] == "work")
{
$response->getBody()->write(json_encode($this->timelineData->getWorkData()));
return $response;
}
// something went wrong
$response->getBody()->write(json_encode(array("errorMessage" => "Error, timeline data not found")));
return $response->withStatus(404);
});
$app->patch("/timelineData/{timeline}/{id}", function (Request $request, Response $response, array $args)
{
$data = $request->getParsedBody();
if ($args["timeline"] == "edu" && $args["id"] != "undefined")
{
if (empty($data["dateFrom"]) || empty($data["dateTo"]) || empty($data["grade"]) || empty($data["course"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
if (!$this->timelineData->updateEduData($data["dateFrom"], $data["dateTo"], $data["grade"], $data["course"], $args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->withStatus(201);
return $response;
}
if ($args["timeline"] == "work" && $args["id"] != "undefined")
{
if (empty($data["dateFrom"]) || empty($data["dateTo"]) || empty($data["companyName"]) || empty($data["area"]) || empty($data["title"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
if (!$this->timelineData->updateWorkData($data["dateFrom"], $data["dateTo"], $data["companyName"], $data["area"], $data["title"], $args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->withStatus(201);
return $response;
}
$response->getBody()->write(json_encode(array("error" => "The correct data was not sent")));
return $response->withStatus(400);
});
$app->delete("/timelineData/{timeline}/{id}", function (Request $request, Response $response, array $args)
{
if ($args["timeline"] == "edu" && $args["id"] != null)
{
if (!$this->timelineData->deleteEduData($args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
return $response;
}
if ($args["timeline"] == "work" && $args["id"] != null)
{
if (!$this->timelineData->deleteWorkData($args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
return $response;
}
$response->getBody()->write(json_encode(array("error" => "The correct data was not sent")));
return $response->withStatus(400);
});
$app->post("/timelineData/{timeline}", function (Request $request, Response $response, array $args)
{
$data = $request->getParsedBody();
if ($args["timeline"] == "edu")
{
if (empty($data["dateFrom"]) || empty($data["dateTo"]) || empty($data["grade"]) || empty($data["course"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$insertedID = $this->timelineData->addEduData($data["dateFrom"], $data["dateTo"], $data["grade"], $data["course"]);
if (!is_int($insertedID))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode(array("ID" => $insertedID)));
$response->withStatus(201);
return $response;
}
if ($args["timeline"] == "work")
{
if (empty($data["dateFrom"]) || empty($data["companyName"]) || empty($data["area"]) || empty($data["title"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
if (empty($data["dateTo"]))
{
$data["dateTo"] = "";
}
$insertedID = $this->timelineData->addWorkData($data["dateFrom"], $data["dateTo"], $data["companyName"], $data["area"], $data["title"]);
if (!is_int($insertedID))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode(array("ID" => $insertedID)));
$response->withStatus(201);
return $response;
}
$response->getBody()->write(json_encode(array("error" => "The correct data was not sent")));
return $response->withStatus(400);
});
}
}

View File

@ -1,9 +1,9 @@
<?php <?php
namespace api; namespace api\user;
use Firebase\JWT\JWT; use Firebase\JWT\JWT;
use PDO; use PDO;
require_once "./config.php"; require_once __DIR__ . "/../utils/config.php";
/** /**
* User Class * User Class

View File

@ -1,18 +1,18 @@
<?php <?php
namespace api; namespace api\user;
use Firebase\JWT\JWT; use Firebase\JWT\JWT;
use PDO; use PDO;
require_once "./config.php"; require_once __DIR__ . "/../utils/config.php";
/** /**
* User Class * User Class
* Define all functions which either check, update or delete user data * Define all functions which either check, update or delete userData data
*/ */
class user class userData
{ {
/** /**
* Check if user exists and can be logged in * Check if userData exists and can be logged in
* @param $username string - Username * @param $username string - Username
* @param $password string - Password * @param $password string - Password
* @return bool - True if logged in, false if not * @return bool - True if logged in, false if not
@ -80,8 +80,8 @@ class user
} }
/** /**
* Send a verification email to the user * Send a verification email to the userData
* @param $email - email address of the user * @param $email - email address of the userData
* @return string - verification code * @return string - verification code
*/ */
function sendResetEmail($email): string function sendResetEmail($email): string
@ -97,7 +97,7 @@ class user
<html lang='en'> <html lang='en'>
<head> <head>
<meta charset='UTF-8'> <meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0'> <meta name='viewport' content='width=device-width, userData-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'> <meta http-equiv='X-UA-Compatible' content='ie=edge'>
<title>Document</title> <title>Document</title>
</head> </head>

154
dist/api/user/userRoutes.php vendored Normal file
View File

@ -0,0 +1,154 @@
<?php
namespace api\user;
require_once __DIR__ . "/../utils/routesInterface.php";
require_once "userData.php";
use api\utils\routesInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;
class userRoutes implements routesInterface
{
private userData $user;
/**
* constructor used to instantiate a base user routes, to be used in the index.php file.
* @param App $app - the slim app used to create the routes
*/
public function __construct(App $app)
{
$this->user = new userData();
$this->createRoutes($app);
}
/**
* creates the routes for the user
* @param App $app - the slim app used to create the routes
* @return void - returns nothing
*/
public function createRoutes(App $app): void
{
$app->post("/user/login", function (Request $request, Response $response)
{
// get request data
$data = $request->getParsedBody();
if (empty($data["username"]) || empty($data["password"]))
{
// uh oh userData sent empty data
return $response->withStatus(400);
}
if ($this->user->checkUser($data["username"], $data["password"]))
{
// yay, userData is logged in
$_SESSION["token"] = $this->user->createToken($data["username"]);
$_SESSION["username"] = $data["username"];
$response->getBody()->write(json_encode(array("token" => $_SESSION["token"])));
return $response;
}
$response->getBody()->write(json_encode(array("error" => "Unauthorised")));
return $response->withStatus(401);
});
$app->get("/user/logout", function (Request $request, Response $response)
{
session_unset();
return $response;
});
$app->get("/user/isLoggedIn", function (Request $request, Response $response)
{
if (empty($_SESSION["token"]) && empty($_SESSION["username"]))
{
// uh oh userData not logged in
return $response->withStatus(401);
}
if (empty($_SESSION["token"]))
{
// userData is logged in but no token was created
$_SESSION["token"] = $this->user->createToken($_SESSION["username"]);
return $response;
}
$response->getBody()->write(json_encode(array("token" => $_SESSION["token"])));
return $response;
});
$app->get("/user/checkResetEmail/{email}", function (Request $request, Response $response, array $args)
{
if (empty($args["email"]))
{
// uh oh sent empty data
return $response->withStatus(400);
}
if ($this->user->checkEmail($args["email"]))
{
// yay email does exist
$_SESSION["resetToken"] = $this->user->sendResetEmail($args["email"]);
$_SESSION["resetEmail"] = $args["email"];
return $response;
}
return $response->withStatus(404);
});
$app->get("/user/resendEmail", function (Request $request, Response $response)
{
if (empty($_SESSION["resetToken"]))
{
// uh oh not authorized to resend email
return $response->withStatus(401);
}
$_SESSION["resetToken"] = $this->user->sendResetEmail($_SESSION["resetEmail"]);
return $response;
});
$app->get("/user/checkResetCode/{code}", function (Request $request, Response $response, array $args)
{
if (empty($args["code"]))
{
// uh oh sent empty data
return $response->withStatus(400);
}
if ($_SESSION["resetToken"] === $args["code"])
{
// yay, code code matches
return $response;
}
return $response->withStatus(401);
});
$app->post("/user/changePassword", function (Request $request, Response $response)
{
if (empty($_SESSION["resetToken"]) && empty($_SESSION["resetEmail"]))
{
// uh oh not authorized to change password
return $response->withStatus(401);
}
$data = $request->getParsedBody();
if (empty($data["password"]))
{
// uh oh sent empty data
return $response->withStatus(400);
}
if ($this->user->changePassword($_SESSION["resetEmail"], $data["password"]))
{
// yay, password changed
unset($_SESSION["resetToken"]);
unset($_SESSION["resetEmail"]);
return $response;
}
return $response->withStatus(500);
});
}
}

View File

@ -1,14 +1,14 @@
<?php <?php
// middleware // middleware
namespace api; namespace api\utils;
session_start(); session_start();
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface; use Psr\Http\Server\RequestHandlerInterface;
use Slim\App;
use Selective\SameSiteCookie\SameSiteCookieConfiguration; use Selective\SameSiteCookie\SameSiteCookieConfiguration;
use Selective\SameSiteCookie\SameSiteCookieMiddleware; use Selective\SameSiteCookie\SameSiteCookieMiddleware;
use Slim\App;
use Slim\Exception\HttpInternalServerErrorException; use Slim\Exception\HttpInternalServerErrorException;
use Slim\Exception\HttpMethodNotAllowedException; use Slim\Exception\HttpMethodNotAllowedException;
use Slim\Exception\HttpNotFoundException; use Slim\Exception\HttpNotFoundException;
@ -80,7 +80,7 @@ class middleware
"rules" => [ "rules" => [
new RequestPathRule([ new RequestPathRule([
"path" => ["/api/projectData", "/api/timelineData/[a-z]*", "/api/projectImage/[0-9]*", "/api/logout"], "path" => ["/api/projectData", "/api/timelineData/[a-z]*", "/api/projectImage/[0-9]*", "/api/logout"],
"ignore" => ["/api/contact", "/api/user/login", "/api/user/changePassword"] "ignore" => ["/api/contact", "/api/userData/login", "/api/userData/changePassword"]
]), ]),
new RequestMethodRule([ new RequestMethodRule([
"ignore" => ["OPTIONS", "GET"] "ignore" => ["OPTIONS", "GET"]

10
dist/api/utils/routesInterface.php vendored Normal file
View File

@ -0,0 +1,10 @@
<?php
namespace api\utils;
use Slim\App;
interface routesInterface
{
public function createRoutes(App $app): void;
}

4
dist/blog/.htaccess vendored Normal file
View File

@ -0,0 +1,4 @@
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.html [QSA,L]

1
dist/blog/index.html vendored Normal file
View File

@ -0,0 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Blog</title></head><body>this is a test<script src="/blog/index.js"></script></body></html>

1
dist/blog/index.js vendored Normal file
View File

@ -0,0 +1 @@
function goToURL(o){let t=o.split("/"),e="";t.includes("blog")&&(e=o),"post"===t[0]&&(e="/blog/"+o),window.history.pushState(null,null,e),document.querySelector("#url").innerHTML=decodeURI(t[t.length-1])}document.addEventListener("DOMContentLoaded",(()=>{goToURL(window.location.pathname)})),window.addEventListener("popstate",(o=>{goToURL(window.history.state)}));

2
dist/css/main.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/index.html vendored

File diff suppressed because one or more lines are too long

2
dist/js/index.js vendored

File diff suppressed because one or more lines are too long

2
dist/js/projects.js vendored
View File

@ -1 +1 @@
const scrollLimit=150;function getProjectData(){fetch("/api/projectData").then((t=>{t.json().then((n=>{t.ok&&n.forEach((t=>{if(1===t.isMainProject)return document.querySelector("#mainProj").innerHTML=`\n\t\t\t\t\t\t<h1>${t.title}</h1>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<img src="${""===t.imgLocation?"../imgs/placeholder.png":t.imgLocation}" alt="">\n\t\t\t\t\t\t\t<div class="flexRow">\n\t\t\t\t\t\t\t\t<p>${t.information}</p>\n\t\t\t\t\t\t\t\t<div class="flexCol">\n\t\t\t\t\t\t\t\t\t<a href="${"N/A"===t.projectLink?"#":t.projectLink}" class="btn btnPrimary boxShadowIn boxShadowOut" ${"N/A"===t.projectLink?'disabled="disabled"':""}>View Project</a>\n\t\t\t\t\t\t\t\t\t<a href="${"N/A"===t.gitLink?"#":t.gitLink}" class="btn btnOutline boxShadowIn boxShadowOut" ${"N/A"===t.gitLink?'disabled="disabled"':""}>Git</a>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t`,null;document.querySelector("#otherProj").innerHTML+=`\n <div class="oProjItem">\n <img src="${""===t.imgLocation?"../imgs/placeholder.png":t.imgLocation}" alt="">\n <div class="flexCol">\n <div>\n \t<h3>${t.title}</h3>\n <p>${t.information}</p>\n </div>\n <div>\n <a href="${"N/A"===t.projectLink?"#":t.projectLink}" class="btn btnPrimary boxShadowIn boxShadowOut"${"N/A"===t.projectLink?'disabled="disabled"':""}>View Project</a>\n <a href="${"N/A"===t.githubLink?"#":t.gitubLink}" class="btn btnOutline boxShadowIn boxShadowOut">${"N/A"===t.githubLink?'disabled="disabled"':""}Git</a>\n </div>\n </div>\n </div>\n `}))}))}))}window.onscroll=()=>{document.body.scrollTop>=150||document.documentElement.scrollTop>=150?document.querySelector("nav").classList.add("scrolled"):document.querySelector("nav").classList.remove("scrolled")},document.querySelector("#goBackToTop").addEventListener("click",(()=>{window.scrollTo(0,0)})),document.addEventListener("DOMContentLoaded",(()=>{getProjectData(),document.getElementById("year").innerHTML=(new Date).getFullYear().toString()})); const scrollLimit=150;function getProjectData(){fetch("/api/projectData").then((t=>{t.json().then((n=>{t.ok&&n.forEach((t=>{if(1===t.isMainProject)return document.querySelector("#mainProj").innerHTML=`\n\t\t\t\t\t\t<h1>${t.title}</h1>\n\t\t\t\t\t\t<div>\n\t\t\t\t\t\t\t<img src="${""===t.imgLocation?"../imgs/placeholder.png":t.imgLocation}" alt="">\n\t\t\t\t\t\t\t<div class="flexRow">\n\t\t\t\t\t\t\t\t<p>${t.information}</p>\n\t\t\t\t\t\t\t\t<div class="flexCol">\n\t\t\t\t\t\t\t\t\t<a href="${"N/A"===t.projectLink?"#":t.projectLink}" class="btn btnPrimary boxShadowIn boxShadowOut" ${"N/A"===t.projectLink?'disabled="disabled"':""}>View Project</a>\n\t\t\t\t\t\t\t\t\t<a href="${"N/A"===t.gitLink?"#":t.gitLink}" class="btn btnOutline boxShadowIn boxShadowOut" ${"N/A"===t.gitLink?'disabled="disabled"':""}>Git</a>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t`,null;document.querySelector("#otherProj").innerHTML+=`\n <div class="oProjItem">\n <img src="${""===t.imgLocation?"../imgs/placeholder.png":t.imgLocation}" alt="">\n <div class="flexCol">\n <div>\n \t<h3>${t.title}</h3>\n <p>${t.information}</p>\n </div>\n <div>\n <a href="${"N/A"===t.projectLink?"#":t.projectLink}" class="btn btnPrimary boxShadowIn boxShadowOut"${"N/A"===t.projectLink?'disabled="disabled"':""}>View Project</a>\n <a href="${"N/A"===t.githubLink?"#":t.gitLink}" class="btn btnOutline boxShadowIn boxShadowOut">${"N/A"===t.githubLink?'disabled="disabled"':""}Git</a>\n </div>\n </div>\n </div>\n `}))}))}))}window.onscroll=()=>{document.body.scrollTop>=150||document.documentElement.scrollTop>=150?document.querySelector("nav").classList.add("scrolled"):document.querySelector("nav").classList.remove("scrolled")},document.querySelector("#goBackToTop").addEventListener("click",(()=>{window.scrollTo(0,0)})),document.addEventListener("DOMContentLoaded",(()=>{getProjectData(),document.getElementById("year").innerHTML=(new Date).getFullYear().toString()}));

Binary file not shown.

2
dist/projects.html vendored
View File

@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Rohit Pai - All Projects</title><link rel="stylesheet" href="css/main.css"><script src="https://kit.fontawesome.com/ed3c25598e.js" crossorigin="anonymous"></script></head><body><nav><input type="checkbox" id="nav-check"> <a href="/"><h1>rohit pai</h1></a><div class="nav-btn"><label for="nav-check"><span></span> <span></span> <span></span></label></div><ul><li><a href="/#about" class="textShadow"><span>&lt;</span>about<span>&gt;</span></a></li><li><a href="/#curriculumVitae" class="textShadow"><span>&lt;</span>cv<span>&gt;</span></a></li><li><a href="#allProjects" class="textShadow active"><span>&lt;</span>projects<span>&gt;</span></a></li><li><a href="/#contact" class="textShadow"><span>&lt;</span>contact<span>&gt;</span></a></li><li><a href="#" class="textShadow"><span>&lt;</span>blog<span>&gt;</span></a></li></ul></nav><header><div><h1>full stack developer</h1><a href="/#sayHello" class="btn btnPrimary boxShadowIn boxShadowOut">Contact Me</a> <a href="#allProjects"><i class="fa-solid fa-chevron-down"></i></a></div></header><main><section id="allProjects"><div class="mainProj" id="mainProj"></div><div class="otherProj" id="otherProj"></div></section></main><footer class="flexRow"><div class="spacer"></div><p>&copy; <span id="year"></span> Rohit Pai all rights reserved</p><div class="button"><button id="goBackToTop"><i class="fa-solid fa-chevron-up"></i></button></div></footer><script src="js/typewriter.js"></script><script src="js/projects.js"></script></body></html> <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Rohit Pai - All Projects</title><link rel="stylesheet" href="css/main.css"><script src="https://kit.fontawesome.com/ed3c25598e.js" crossorigin="anonymous"></script></head><body><nav><input type="checkbox" id="nav-check"> <a href="/"><h1>rohit pai</h1></a><div class="nav-btn"><label for="nav-check"><span></span> <span></span> <span></span></label></div><ul><li><a href="/#about" class="textShadow"><span>&lt;</span>about<span>&gt;</span></a></li><li><a href="/#curriculumVitae" class="textShadow"><span>&lt;</span>cv<span>&gt;</span></a></li><li><a href="#allProjects" class="textShadow active"><span>&lt;</span>projects<span>&gt;</span></a></li><li><a href="/#contact" class="textShadow"><span>&lt;</span>contact<span>&gt;</span></a></li><li><a href="/blog" class="textShadow"><span>&lt;</span>blog<span>&gt;</span></a></li></ul></nav><header><div><h1>full stack developer</h1><a href="/#sayHello" class="btn btnPrimary boxShadowIn boxShadowOut">Contact Me</a> <a href="#allProjects"><i class="fa-solid fa-chevron-down"></i></a></div></header><main><section id="allProjects"><div class="mainProj" id="mainProj"></div><div class="otherProj" id="otherProj"></div></section></main><footer class="flexRow"><div class="spacer"></div><p>&copy; <span id="year"></span> Rohit Pai all rights reserved</p><div class="button"><button id="goBackToTop"><i class="fa-solid fa-chevron-up"></i></button></div></footer><script src="js/typewriter.js"></script><script src="js/projects.js"></script></body></html>

View File

@ -40,8 +40,8 @@ gulp.task("minifyJS", () =>
gulp.task("movePHPFiles", () => gulp.task("movePHPFiles", () =>
{ {
return gulp.src("src/api/*.php") return gulp.src("src/api/**/*.php")
.pipe(gulp.dest("dist/api")) .pipe(gulp.dest("dist/api/"))
}); });
gulp.task("watchFiles", () => gulp.task("watchFiles", () =>
@ -49,7 +49,7 @@ gulp.task("watchFiles", () =>
gulp.watch("src/**/*.html", gulp.task("minifyHTML")); gulp.watch("src/**/*.html", gulp.task("minifyHTML"));
gulp.watch("src/**/*.css", gulp.task("minifyCSS")); gulp.watch("src/**/*.css", gulp.task("minifyCSS"));
gulp.watch("src/**/*.js", gulp.task("minifyJS")); gulp.watch("src/**/*.js", gulp.task("minifyJS"));
gulp.watch("src/api/*.php", gulp.task("movePHPFiles")) gulp.watch("src/api/**/*.php", gulp.task("movePHPFiles"))
}); });
gulp.task("browserSync", () => gulp.task("browserSync", () =>

97
src/api/blog/blogData.php Normal file
View File

@ -0,0 +1,97 @@
<?php
namespace api\blog;
use PDO;
require_once __DIR__ . "/../utils/config.php";
/**
* Blog Data Class
* Define all functions which either get, update, create or delete posts
*/
class blogData
{
/**
* Get all blog posts
* @return array - Array of all blog posts or error message
*/
function getBlogPosts(): array
{
$conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, body, tags FROM blog ORDER BY dateCreated DESC;");
$stmt->execute();
// set the resulting array to associative
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
if ($result)
{
return $result;
}
return array("errorMessage" => "Error, blog data not found");
}
/**
* Get a blog post with the given ID
* @param string $ID - ID of the blog post to get
* @return array - Array of all blog posts or error message
*/
function getBlogPost(string $ID): array
{
$conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, tags FROM blog WHERE ID = :ID;");
$stmt->bindParam(":ID", $ID);
$stmt->execute();
// set the resulting array to associative
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result)
{
return $result;
}
return array("errorMessage" => "Error, blog post could not found");
}
/**
* Get the latest blog post
* @return array - Array of the latest blog post or error message
*/
function getLatestBlogPost(): array
{
$conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, tags FROM blog ORDER BY dateCreated DESC LIMIT 1;");
$stmt->execute();
// set the resulting array to associative
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result)
{
return $result;
}
return array("errorMessage" => "Error, blog post could not found");
}
/**
* Get featured blog post
* @return array - Array of the featured blog post or error message
*/
function getFeaturedBlogPost(): array
{
$conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, tags FROM blog WHERE featured = 1;");
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result)
{
return $result;
}
return array("errorMessage" => "Error, blog post could not found");
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace api\blog;
require_once __DIR__ . "/../utils/routesInterface.php";
require_once "blogData.php";
use api\utils\routesInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;
class blogRoutes implements routesInterface
{
private blogData $blogData;
/**
* constructor used to instantiate a base blog routes, to be used in the index.php file.
* @param App $app - the slim app used to create the routes
*/
public function __construct(App $app)
{
$this->blogData = new blogData();
$this->createRoutes($app);
}
/**
* creates the routes for the blog
* @param App $app - the slim app used to create the routes
* @return void - returns nothing
*/
public function createRoutes(App $app): void
{
// TODO: Implement createRoutes() method.
}
}

View File

@ -1,26 +1,25 @@
<?php /** @noinspection PhpIncludeInspection */ <?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
////////////////// Index file ////////////// ////////////////// Index file //////////////
/// Creates base routes and runs /// /// Creates base routes and runs ///
/// respective functions /// /// respective functions ///
//////////////////////////////////////////// ////////////////////////////////////////////
//require “routes.php”;
require "../vendor/autoload.php"; require "../vendor/autoload.php";
include "middleware.php"; require "utils/middleware.php";
include "timelineData.php"; require "timeline/timelineRoutes.php";
include "projectData.php"; require "project/projectRoutes.php";
include "user.php"; require "user/userRoutes.php";
require "blog/blogRoutes.php";
use api\middleware; use api\blog\blogRoutes;
use api\projectData; use api\project\projectRoutes;
use api\timelineData; use api\timeline\timelineRoutes;
use api\user; use api\user\userRoutes;
use api\utils\middleware;
use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ServerRequestInterface as Request;
use Selective\SameSiteCookie\SameSiteCookieConfiguration;
use Selective\SameSiteCookie\SameSiteCookieMiddleware;
use Slim\Factory\AppFactory; use Slim\Factory\AppFactory;
use Tuupola\Middleware\JwtAuthentication;
// Start slim // Start slim
$app = AppFactory::create(); $app = AppFactory::create();
@ -31,310 +30,26 @@ $app->setBasePath("/api");
// Add middleware // Add middleware
new middleware($app); new middleware($app);
$timelineData = new timelineData(); new timelineRoutes($app);
$projectData = new projectData(); new projectRoutes($app);
$user = new user(); new blogRoutes($app);
new userRoutes($app);
$app->get("/timelineData/{timeline}", function (Request $request, Response $response, array $args)
{
global $timelineData;
//check if route is available if it is get the data
//otherwise return an error
if($args["timeline"] == "edu")
{
$response->getBody()->write(json_encode($timelineData->getEduData()));
return $response;
}
if($args["timeline"] == "work")
{
$response->getBody()->write(json_encode($timelineData->getWorkData()));
return $response;
}
// something went wrong
$response->getBody()->write(json_encode(array("errorMessage" => "Error, timeline data not found")));
return $response->withStatus(404);
});
$app->patch("/timelineData/{timeline}/{id}", function (Request $request, Response $response, array $args)
{
global $timelineData;
$data = $request->getParsedBody();
if ($args["timeline"] == "edu" && $args["id"] != "undefined")
{
if (empty($data["dateFrom"]) || empty($data["dateTo"]) || empty($data["grade"]) || empty($data["course"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
if (!$timelineData->updateEduData($data["dateFrom"], $data["dateTo"], $data["grade"], $data["course"], $args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->withStatus(201);
return $response;
}
if ($args["timeline"] == "work" && $args["id"] != "undefined")
{
if (empty($data["dateFrom"]) || empty($data["dateTo"]) || empty($data["companyName"]) || empty($data["area"]) || empty($data["title"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
if (!$timelineData->updateWorkData($data["dateFrom"], $data["dateTo"], $data["companyName"], $data["area"], $data["title"], $args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->withStatus(201);
return $response;
}
$response->getBody()->write(json_encode(array("error" => "The correct data was not sent")));
return $response->withStatus(400);
});
$app->delete("/timelineData/{timeline}/{id}", function (Request $request, Response $response, array $args)
{
global $timelineData;
if ($args["timeline"] == "edu" && $args["id"] != null)
{
if (!$timelineData->deleteEduData($args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
return $response;
}
if ($args["timeline"] == "work" && $args["id"] != null)
{
if (!$timelineData->deleteWorkData($args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
return $response;
}
$response->getBody()->write(json_encode(array("error" => "The correct data was not sent")));
return $response->withStatus(400);
});
$app->post("/timelineData/{timeline}", function (Request $request, Response $response, array $args)
{
global $timelineData;
$data = $request->getParsedBody();
if ($args["timeline"] == "edu")
{
if (empty($data["dateFrom"]) || empty($data["dateTo"]) || empty($data["grade"]) || empty($data["course"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$insertedID = $timelineData->addEduData($data["dateFrom"], $data["dateTo"], $data["grade"], $data["course"]);
if (!is_int($insertedID))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode(array("ID" => $insertedID)));
$response->withStatus(201);
return $response;
}
if ($args["timeline"] == "work")
{
if (empty($data["dateFrom"]) || empty($data["companyName"]) || empty($data["area"]) || empty($data["title"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
if (empty($data["dateTo"]))
{
$data["dateTo"] = "";
}
$insertedID = $timelineData->addWorkData($data["dateFrom"], $data["dateTo"], $data["companyName"], $data["area"], $data["title"]);
if (!is_int($insertedID))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode(array("ID" => $insertedID)));
$response->withStatus(201);
return $response;
}
$response->getBody()->write(json_encode(array("error" => "The correct data was not sent")));
return $response->withStatus(400);
});
$app->get("/projectData", function (Request $request, Response $response)
{
global $projectData;
$result = $projectData->getProjectData();
$json = json_encode($result);
$response->getBody()->write($json);
if(array_key_exists("errorMessage", $result))
{
$response = $response->withStatus(404);
}
//use content type json to indicate json data on frontend.
return $response;
});
$app->patch("/projectData/{id}", function (Request $request, Response $response, array $args)
{
global $projectData;
$data = $request->getParsedBody();
if ($args["id"] != "undefined")
{
if (empty($data["title"]) || empty($data["isMainProject"]) || empty($data["information"]) || empty($data["gitLink"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$update = $projectData->updateProjectData($args["id"], $data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["gitLink"]);
if ($update === "unset main project")
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Can't unset project as main project, try updating another project as the main project")));
return $response->withStatus(400);
}
if (!$update)
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
return $response;
}
$response->getBody()->write(json_encode(array("error" => "Please provide an ID")));
return $response->withStatus(400);
});
$app->delete("/projectData/{id}", function (Request $request, Response $response, array $args)
{
global $projectData;
if ($args["id"] != null)
{
$message = $projectData->deleteProjectData($args["id"]);
if ($message === "error")
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong or the project with ID ".$args["id"]."does not exist")));
return $response->withStatus(500);
}
if ($message === "cannot delete")
{
//uh oh cannot delete the main project
$response->getBody()->write(json_encode(array("error" => "Cannot delete the main project")));
return $response->withStatus(409);
}
return $response;
}
$response->getBody()->write(json_encode(array("error" => "Please provide an ID")));
return $response->withStatus(400);
});
$app->post("/projectData", function (Request $request, Response $response)
{
global $projectData;
$data = $request->getParsedBody();
if (empty($data["title"]) || empty($data["isMainProject"]) || empty($data["information"]) || empty($data["gitLink"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$insertedID = $projectData->addProjectData($data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["gitLink"]);
if (!is_int($insertedID))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong", "message" => $insertedID)));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode(array("ID" => $insertedID)));
return $response;
});
$app->post("/projectImage/{id}", function (Request $request, Response $response, array $args)
{
global $projectData;
$files = $request->getUploadedFiles();
if (empty($args["id"]) || empty($files))
{
// uh oh only some of the data was sent
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$message = $projectData->uploadImage($args["id"], $files["img"]);
if (!is_array($message))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => $message)));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode($message));
return $response;
});
// misc routes
$app->post("/contact", function (Request $request, Response $response) $app->post("/contact", function (Request $request, Response $response)
{ {
$data = $request->getParsedBody(); $data = $request->getParsedBody();
if(empty($data["fName"]) || empty($data["lName"]) || empty($data["email"]) || empty($data["subject"]) || empty($data["message"])) if(empty($data["fName"]) || empty($data["lName"]) || empty($data["email"]) || empty($data["subject"]) || empty($data["message"]))
{ {
$response->getBody()->write(json_encode(array("errorMessage" => "Please fill out all the fields"))); $response->getBody()->write(json_encode(array("errorMessage" => "Please fill out all the fields")));
return $response->withStatus(400); return $response->withStatus(400);
} }
if (!filter_var($data["email"], FILTER_VALIDATE_EMAIL)) if (!filter_var($data["email"], FILTER_VALIDATE_EMAIL))
{ {
$response->getBody()->write(json_encode(array("errorMessage" => "Email is not the correct format"))); $response->getBody()->write(json_encode(array("errorMessage" => "Email is not the correct format")));
return $response->withStatus(400); return $response->withStatus(400);
} }
// email form filler/conatcter // email form filler/conatcter
@ -343,12 +58,12 @@ $app->post("/contact", function (Request $request, Response $response)
$headers1 .= "MIME-Version: 1.0\r\n"; $headers1 .= "MIME-Version: 1.0\r\n";
$headers1 .= "Content-Type: text/html; charset=UTF-8\r\n"; $headers1 .= "Content-Type: text/html; charset=UTF-8\r\n";
$message1 = " $message1 = <<<HEREA
<html lang=\"en\"> <html lang="en">
<head> <head>
<title>{$data['subject']}</title> <title>{$data['subject']}</title>
<style> <style>
@import url(\"https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400;1,700&family=Share+Tech+Mono&family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap\"); @import url("https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400;1,700&family=Share+Tech+Mono&family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap");
body { body {
font-family: Noto Sans KR, sans-serif; font-family: Noto Sans KR, sans-serif;
font-style: normal; font-style: normal;
@ -403,17 +118,17 @@ $app->post("/contact", function (Request $request, Response $response)
<tr> <tr>
<td>{$data['fName']}</td> <td>{$data['fName']}</td>
<td>{$data['lName']}</td> <td>{$data['lName']}</td>
<td><a href=\"mailto:{$data['email']}\">{$data['email']}</a></td> <td><a href="mailto:{$data['email']}">{$data['email']}</a></td>
<td>{$data['subject']}</td> <td>{$data['subject']}</td>
<td>{$data['message']}</td> <td>{$data['message']}</td>
</tr> </tr>
</table> </table>
<br> <br>
<hr> <hr>
<p>Regards, <br> Rohit Pai <br> <a href=\"mailto:rohit@rohitpai.co.uk\">rohit@rohitpai.co.uk</a> <p>Regards, <br> Rohit Pai <br> <a href="mailto:rohit@rohitpai.co.uk">rohit@rohitpai.co.uk</a>
</body> </body>
</html> </html>
"; HEREA;
mail($data["email"], $data["subject"], $message1, $headers1); mail($data["email"], $data["subject"], $message1, $headers1);
@ -423,12 +138,12 @@ $app->post("/contact", function (Request $request, Response $response)
$headers2 .= "MIME-Version: 1.0\r\n"; $headers2 .= "MIME-Version: 1.0\r\n";
$headers2 .= "Content-Type: text/html; charset=UTF-8\r\n"; $headers2 .= "Content-Type: text/html; charset=UTF-8\r\n";
$message2 = " $message2 = <<<HEREB
<html lang=\"en\"> <html lang="en">
<head> <head>
<title>{$data['subject']}</title> <title>{$data['subject']}</title>
<style> <style>
@import url(\"https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400;1,700&family=Share+Tech+Mono&family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap\"); @import url("https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400;1,700&family=Share+Tech+Mono&family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap");
body { body {
font-family: Noto Sans KR, sans-serif; font-family: Noto Sans KR, sans-serif;
font-style: normal; font-style: normal;
@ -481,147 +196,17 @@ $app->post("/contact", function (Request $request, Response $response)
<tr> <tr>
<td>{$data['fName']}</td> <td>{$data['fName']}</td>
<td>{$data['lName']}</td> <td>{$data['lName']}</td>
<td><a href=\"mailto:{$data['email']}\">{$data['email']}</a></td> <td><a href="mailto:{$data['email']}">{$data['email']}</a></td>
<td>{$data['subject']}</td> <td>{$data['subject']}</td>
<td>{$data['message']}</td> <td>{$data['message']}</td>
</tr> </tr>
</table> </table>
</body> </body>
</html> </html>
"; HEREB;
mail("rohit@rohitpai.co.uk", "{$data['fName']} {$data['lName']} filled in the form", $message2, $headers2); mail("rohit@rohitpai.co.uk", "{$data['fName']} {$data['lName']} filled in the form", $message2, $headers2);
return $response->withStatus(201); return $response->withStatus(201);
}); });
$app->post("/user/login", function (Request $request, Response $response)
{
global $user;
// get request data
$data = $request->getParsedBody();
if (empty($data["username"]) || empty($data["password"]))
{
// uh oh user sent empty data
return $response->withStatus(400);
}
if ($user->checkUser($data["username"], $data["password"]))
{
// yay, user is logged in
$_SESSION["token"] = $user->createToken($data["username"]);
$_SESSION["username"] = $data["username"];
$response->getBody()->write(json_encode(array("token" => $_SESSION["token"])));
return $response;
}
$response->getBody()->write(json_encode(array("error" => "Unauthorised")));
return $response->withStatus(401);
});
$app->get("/user/logout", function (Request $request, Response $response)
{
session_unset();
return $response;
});
$app->get("/user/isLoggedIn", function (Request $request, Response $response)
{
global $user;
if (empty($_SESSION["token"]) && empty($_SESSION["username"]))
{
// uh oh user not logged in
return $response->withStatus(401);
}
if (empty($_SESSION["token"]))
{
// user is logged in but no token was created
$_SESSION["token"] = $user->createToken($_SESSION["username"]);
return $response;
}
$response->getBody()->write(json_encode(array("token" => $_SESSION["token"])));
return $response;
});
$app->get("/user/checkResetEmail/{email}", function (Request $request, Response $response, array $args)
{
global $user;
if (empty($args["email"]))
{
// uh oh sent empty data
return $response->withStatus(400);
}
if ($user->checkEmail($args["email"]))
{
// yay email does exist
$_SESSION["resetToken"] = $user->sendResetEmail($args["email"]);
$_SESSION["resetEmail"] = $args["email"];
return $response;
}
return $response->withStatus(404);
});
$app->get("/user/resendEmail", function (Request $request, Response $response)
{
if (empty($_SESSION["resetToken"]))
{
// uh oh not authorized to resend email
return $response->withStatus(401);
}
global $user;
$_SESSION["resetToken"] = $user->sendResetEmail($_SESSION["resetEmail"]);
return $response;
});
$app->get("/user/checkResetCode/{code}", function (Request $request, Response $response, array $args)
{
if (empty($args["code"]))
{
// uh oh sent empty data
return $response->withStatus(400);
}
if ($_SESSION["resetToken"] === $args["code"])
{
// yay, code code matches
return $response;
}
return $response->withStatus(401);
});
$app->post("/user/changePassword", function (Request $request, Response $response)
{
global $user;
if (empty($_SESSION["resetToken"]) && empty($_SESSION["resetEmail"]))
{
// uh oh not authorized to change password
return $response->withStatus(401);
}
$data = $request->getParsedBody();
if (empty($data["password"]))
{
// uh oh sent empty data
return $response->withStatus(400);
}
if ($user->changePassword($_SESSION["resetEmail"], $data["password"]))
{
// yay, password changed
unset($_SESSION["resetToken"]);
unset($_SESSION["resetEmail"]);
return $response;
}
return $response->withStatus(500);
});
$app->run(); $app->run();

View File

@ -1,9 +1,9 @@
<?php <?php
namespace api; namespace api\project;
use PDO; use PDO;
use Psr\Http\Message\UploadedFileInterface; use Psr\Http\Message\UploadedFileInterface;
require_once "./config.php"; require_once __DIR__ . "/../utils/config.php";
/** /**
* Project Data Class * Project Data Class

View File

@ -0,0 +1,153 @@
<?php
namespace api\project;
require_once __DIR__ . "/../utils/routesInterface.php";
require_once "projectData.php";
use api\utils\routesInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;
class projectRoutes implements routesInterface
{
private projectData $projectData;
/**
* constructor used to instantiate a base project routes, to be used in the index.php file.
* @param App $app - the slim app used to create the routes
*/
public function __construct(App $app)
{
$this->projectData = new projectData();
$this->createRoutes($app);
}
/**
* creates the routes for the project
* @param App $app - the slim app used to create the routes
* @return void - returns nothing
*/
public function createRoutes(App $app): void
{
$app->get("/projectData", function (Request $request, Response $response)
{
$result = $this->projectData->getProjectData();
$json = json_encode($result);
$response->getBody()->write($json);
if(array_key_exists("errorMessage", $result))
{
$response = $response->withStatus(404);
}
//use content type json to indicate json data on frontend.
return $response;
});
$app->patch("/projectData/{id}", function (Request $request, Response $response, array $args)
{
$data = $request->getParsedBody();
if ($args["id"] != "undefined")
{
if (empty($data["title"]) || empty($data["isMainProject"]) || empty($data["information"]) || empty($data["gitLink"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$update = $this->projectData->updateProjectData($args["id"], $data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["gitLink"]);
if ($update === "unset main project")
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Can't unset project as main project, try updating another project as the main project")));
return $response->withStatus(400);
}
if (!$update)
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
return $response;
}
$response->getBody()->write(json_encode(array("error" => "Please provide an ID")));
return $response->withStatus(400);
});
$app->delete("/projectData/{id}", function (Request $request, Response $response, array $args)
{
if ($args["id"] != null)
{
$message = $this->projectData->deleteProjectData($args["id"]);
if ($message === "error")
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong or the project with ID ".$args["id"]."does not exist")));
return $response->withStatus(500);
}
if ($message === "cannot delete")
{
//uh oh cannot delete the main project
$response->getBody()->write(json_encode(array("error" => "Cannot delete the main project")));
return $response->withStatus(409);
}
return $response;
}
$response->getBody()->write(json_encode(array("error" => "Please provide an ID")));
return $response->withStatus(400);
});
$app->post("/projectData", function (Request $request, Response $response)
{
$data = $request->getParsedBody();
if (empty($data["title"]) || empty($data["isMainProject"]) || empty($data["information"]) || empty($data["gitLink"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$insertedID = $this->projectData->addProjectData($data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["gitLink"]);
if (!is_int($insertedID))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong", "message" => $insertedID)));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode(array("ID" => $insertedID)));
return $response;
});
$app->post("/projectImage/{id}", function (Request $request, Response $response, array $args)
{
$files = $request->getUploadedFiles();
if (empty($args["id"]) || empty($files))
{
// uh oh only some of the data was sent
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$message = $this->projectData->uploadImage($args["id"], $files["img"]);
if (!is_array($message))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => $message)));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode($message));
return $response;
});
}
}

View File

@ -1,10 +1,10 @@
<?php <?php
namespace api; namespace api\timeline;
use PDO; use PDO;
require_once "./config.php"; require_once __DIR__ . "/../utils/config.php";
/** /**
* TimelineData class * TimelineData class

View File

@ -0,0 +1,186 @@
<?php
namespace api\timeline;
require_once __DIR__ . "/../utils/routesInterface.php";
require_once "timelineData.php";
use api\utils\routesInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;
class timelineRoutes implements routesInterface
{
private timelineData $timelineData;
/**
* constructor used to instantiate a base timeline routes, to be used in the index.php file.
* @param App $app - the slim app used to create the routes
*/
public function __construct(App $app)
{
$this->timelineData = new timelineData();
$this->createRoutes($app);
}
/**
* creates the routes for the timeline
* @param App $app - the slim app used to create the routes
* @return void - returns nothing
*/
public function createRoutes(App $app): void
{
$app->get("/timelineData/{timeline}", function (Request $request, Response $response, array $args)
{
//check if route is available if it is get the data
//otherwise return an error
if ($args["timeline"] == "edu")
{
$response->getBody()->write(json_encode($this->timelineData->getEduData()));
return $response;
}
if($args["timeline"] == "work")
{
$response->getBody()->write(json_encode($this->timelineData->getWorkData()));
return $response;
}
// something went wrong
$response->getBody()->write(json_encode(array("errorMessage" => "Error, timeline data not found")));
return $response->withStatus(404);
});
$app->patch("/timelineData/{timeline}/{id}", function (Request $request, Response $response, array $args)
{
$data = $request->getParsedBody();
if ($args["timeline"] == "edu" && $args["id"] != "undefined")
{
if (empty($data["dateFrom"]) || empty($data["dateTo"]) || empty($data["grade"]) || empty($data["course"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
if (!$this->timelineData->updateEduData($data["dateFrom"], $data["dateTo"], $data["grade"], $data["course"], $args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->withStatus(201);
return $response;
}
if ($args["timeline"] == "work" && $args["id"] != "undefined")
{
if (empty($data["dateFrom"]) || empty($data["dateTo"]) || empty($data["companyName"]) || empty($data["area"]) || empty($data["title"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
if (!$this->timelineData->updateWorkData($data["dateFrom"], $data["dateTo"], $data["companyName"], $data["area"], $data["title"], $args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->withStatus(201);
return $response;
}
$response->getBody()->write(json_encode(array("error" => "The correct data was not sent")));
return $response->withStatus(400);
});
$app->delete("/timelineData/{timeline}/{id}", function (Request $request, Response $response, array $args)
{
if ($args["timeline"] == "edu" && $args["id"] != null)
{
if (!$this->timelineData->deleteEduData($args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
return $response;
}
if ($args["timeline"] == "work" && $args["id"] != null)
{
if (!$this->timelineData->deleteWorkData($args["id"]))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
return $response;
}
$response->getBody()->write(json_encode(array("error" => "The correct data was not sent")));
return $response->withStatus(400);
});
$app->post("/timelineData/{timeline}", function (Request $request, Response $response, array $args)
{
$data = $request->getParsedBody();
if ($args["timeline"] == "edu")
{
if (empty($data["dateFrom"]) || empty($data["dateTo"]) || empty($data["grade"]) || empty($data["course"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
$insertedID = $this->timelineData->addEduData($data["dateFrom"], $data["dateTo"], $data["grade"], $data["course"]);
if (!is_int($insertedID))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode(array("ID" => $insertedID)));
$response->withStatus(201);
return $response;
}
if ($args["timeline"] == "work")
{
if (empty($data["dateFrom"]) || empty($data["companyName"]) || empty($data["area"]) || empty($data["title"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400);
}
if (empty($data["dateTo"]))
{
$data["dateTo"] = "";
}
$insertedID = $this->timelineData->addWorkData($data["dateFrom"], $data["dateTo"], $data["companyName"], $data["area"], $data["title"]);
if (!is_int($insertedID))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => "Something went wrong")));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode(array("ID" => $insertedID)));
$response->withStatus(201);
return $response;
}
$response->getBody()->write(json_encode(array("error" => "The correct data was not sent")));
return $response->withStatus(400);
});
}
}

138
src/api/user/userData.php Normal file
View File

@ -0,0 +1,138 @@
<?php
namespace api\user;
use Firebase\JWT\JWT;
use PDO;
require_once __DIR__ . "/../utils/config.php";
/**
* User Class
* Define all functions which either check, update or delete userData data
*/
class userData
{
/**
* Check if userData exists and can be logged in
* @param $username string - Username
* @param $password string - Password
* @return bool - True if logged in, false if not
*/
function checkUser(string $username, string $password): bool
{
$conn = dbConn();
$stmt = $conn->prepare("SELECT * FROM users WHERE username = :username");
$stmt->bindParam(":username", $username);
$stmt->execute();
// set the resulting array to associative
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
if ($result)
{
if (password_verify($password, $result[0]["password"]))
{
return true;
}
return false;
}
return false;
}
/**
* Create a JWT token
* @param $username string - Username
* @return string - JWT token
*/
function createToken(string $username): string
{
$now = time();
$future = strtotime('+6 hour',$now);
$secretKey = getSecretKey();
$payload = [
"jti"=>$username,
"iat"=>$now,
"exp"=>$future
];
return JWT::encode($payload,$secretKey,"HS256");
}
/**
* Check if email is already in use
* @param string $email - Email to check
* @return bool - True if email exists, false if not
*/
function checkEmail(string $email): bool
{
$conn = dbConn();
$stmt = $conn->prepare("SELECT * FROM users WHERE email = :email");
$stmt->bindParam(":email", $email);
$stmt->execute();
// set the resulting array to associative
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
if ($result)
{
return true;
}
return false;
}
/**
* Send a verification email to the userData
* @param $email - email address of the userData
* @return string - verification code
*/
function sendResetEmail($email): string
{
//generate a random token and email the address
$token = uniqid("rpe-");
$headers1 = "From: noreply@rohitpai.co.uk\r\n";
$headers1 .= "MIME-Version: 1.0\r\n";
$headers1 .= "Content-Type: text/html; charset=UTF-8\r\n";
$message = "
<!doctype html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, userData-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'>
<title>Document</title>
</head>
<body>
<h1>Reset Password Verification Code</h1>
<br>
<p>Please enter the following code to reset your password: $token</p>
</body>
</html>
";
mail($email, "Reset Password Verification Code", $message, $headers1);
return $token;
}
/**
* Change password for an email with new password
* @param $email string Email
* @param $password string Password
* @return bool - true if the password was changed, false if not
*/
function changePassword(string $email, string $password): bool
{
$conn = dbConn();
$stmt = $conn->prepare("UPDATE users SET password = :password WHERE email = :email");
$newPwd = password_hash($password, PASSWORD_BCRYPT);
$stmt->bindParam(":password", $newPwd);
$stmt->bindParam(":email", $email);
if ($stmt->execute())
{
return true;
}
return false;
}
}

154
src/api/user/userRoutes.php Normal file
View File

@ -0,0 +1,154 @@
<?php
namespace api\user;
require_once __DIR__ . "/../utils/routesInterface.php";
require_once "userData.php";
use api\utils\routesInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;
class userRoutes implements routesInterface
{
private userData $user;
/**
* constructor used to instantiate a base user routes, to be used in the index.php file.
* @param App $app - the slim app used to create the routes
*/
public function __construct(App $app)
{
$this->user = new userData();
$this->createRoutes($app);
}
/**
* creates the routes for the user
* @param App $app - the slim app used to create the routes
* @return void - returns nothing
*/
public function createRoutes(App $app): void
{
$app->post("/user/login", function (Request $request, Response $response)
{
// get request data
$data = $request->getParsedBody();
if (empty($data["username"]) || empty($data["password"]))
{
// uh oh userData sent empty data
return $response->withStatus(400);
}
if ($this->user->checkUser($data["username"], $data["password"]))
{
// yay, userData is logged in
$_SESSION["token"] = $this->user->createToken($data["username"]);
$_SESSION["username"] = $data["username"];
$response->getBody()->write(json_encode(array("token" => $_SESSION["token"])));
return $response;
}
$response->getBody()->write(json_encode(array("error" => "Unauthorised")));
return $response->withStatus(401);
});
$app->get("/user/logout", function (Request $request, Response $response)
{
session_unset();
return $response;
});
$app->get("/user/isLoggedIn", function (Request $request, Response $response)
{
if (empty($_SESSION["token"]) && empty($_SESSION["username"]))
{
// uh oh userData not logged in
return $response->withStatus(401);
}
if (empty($_SESSION["token"]))
{
// userData is logged in but no token was created
$_SESSION["token"] = $this->user->createToken($_SESSION["username"]);
return $response;
}
$response->getBody()->write(json_encode(array("token" => $_SESSION["token"])));
return $response;
});
$app->get("/user/checkResetEmail/{email}", function (Request $request, Response $response, array $args)
{
if (empty($args["email"]))
{
// uh oh sent empty data
return $response->withStatus(400);
}
if ($this->user->checkEmail($args["email"]))
{
// yay email does exist
$_SESSION["resetToken"] = $this->user->sendResetEmail($args["email"]);
$_SESSION["resetEmail"] = $args["email"];
return $response;
}
return $response->withStatus(404);
});
$app->get("/user/resendEmail", function (Request $request, Response $response)
{
if (empty($_SESSION["resetToken"]))
{
// uh oh not authorized to resend email
return $response->withStatus(401);
}
$_SESSION["resetToken"] = $this->user->sendResetEmail($_SESSION["resetEmail"]);
return $response;
});
$app->get("/user/checkResetCode/{code}", function (Request $request, Response $response, array $args)
{
if (empty($args["code"]))
{
// uh oh sent empty data
return $response->withStatus(400);
}
if ($_SESSION["resetToken"] === $args["code"])
{
// yay, code code matches
return $response;
}
return $response->withStatus(401);
});
$app->post("/user/changePassword", function (Request $request, Response $response)
{
if (empty($_SESSION["resetToken"]) && empty($_SESSION["resetEmail"]))
{
// uh oh not authorized to change password
return $response->withStatus(401);
}
$data = $request->getParsedBody();
if (empty($data["password"]))
{
// uh oh sent empty data
return $response->withStatus(400);
}
if ($this->user->changePassword($_SESSION["resetEmail"], $data["password"]))
{
// yay, password changed
unset($_SESSION["resetToken"]);
unset($_SESSION["resetEmail"]);
return $response;
}
return $response->withStatus(500);
});
}
}

View File

@ -1,14 +1,14 @@
<?php <?php
// middleware // middleware
namespace api; namespace api\utils;
session_start(); session_start();
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface; use Psr\Http\Server\RequestHandlerInterface;
use Slim\App;
use Selective\SameSiteCookie\SameSiteCookieConfiguration; use Selective\SameSiteCookie\SameSiteCookieConfiguration;
use Selective\SameSiteCookie\SameSiteCookieMiddleware; use Selective\SameSiteCookie\SameSiteCookieMiddleware;
use Slim\App;
use Slim\Exception\HttpInternalServerErrorException; use Slim\Exception\HttpInternalServerErrorException;
use Slim\Exception\HttpMethodNotAllowedException; use Slim\Exception\HttpMethodNotAllowedException;
use Slim\Exception\HttpNotFoundException; use Slim\Exception\HttpNotFoundException;
@ -80,7 +80,7 @@ class middleware
"rules" => [ "rules" => [
new RequestPathRule([ new RequestPathRule([
"path" => ["/api/projectData", "/api/timelineData/[a-z]*", "/api/projectImage/[0-9]*", "/api/logout"], "path" => ["/api/projectData", "/api/timelineData/[a-z]*", "/api/projectImage/[0-9]*", "/api/logout"],
"ignore" => ["/api/contact", "/api/user/login", "/api/user/changePassword"] "ignore" => ["/api/contact", "/api/userData/login", "/api/userData/changePassword"]
]), ]),
new RequestMethodRule([ new RequestMethodRule([
"ignore" => ["OPTIONS", "GET"] "ignore" => ["OPTIONS", "GET"]

View File

@ -0,0 +1,10 @@
<?php
namespace api\utils;
use Slim\App;
interface routesInterface
{
public function createRoutes(App $app): void;
}

11
src/blog/index.html Normal file
View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Blog</title>
</head>
<body>
this is a test
<script src="/blog/index.js"></script>
</body>
</html>

41
src/blog/index.js Normal file
View File

@ -0,0 +1,41 @@
document.addEventListener('DOMContentLoaded', () =>
{
goToURL(window.location.pathname);
});
window.addEventListener('popstate', e =>
{
goToURL(window.history.state);
});
/**
* goToURL tries to go to the specified URL if not shows the error page (not yet implemented)
* @param {string} url of the page
*/
function goToURL(url)
{
// Get the current URL and split it into an array
let urlArray = url.split('/');
let newUrl = "";
if (urlArray.includes('blog'))
{
newUrl = url;
}
// Check if the URL is a post page
if (urlArray[0] === 'post')
{
// Create a new URL with the dynamic part
newUrl = "/blog/" + url;
}
// Update the URL in the browser without reloading the page
window.history.pushState(null, null, newUrl);
// Get the dynamic part of the URL
document.querySelector("#url").innerHTML = decodeURI(urlArray[urlArray.length - 1]);
}

View File

@ -1,145 +1,135 @@
-- MariaDB dump 10.19 Distrib 10.9.4-MariaDB, for Linux (x86_64) -- phpMyAdmin SQL Dump
-- version 5.1.1
-- https://www.phpmyadmin.net/
-- --
-- Host: sql276.main-hosting.eu Database: u987021215_cms -- Host: 127.0.0.1:3306
-- ------------------------------------------------------ -- Generation Time: Jun 05, 2023 at 12:09 PM
-- Server version 10.5.12-MariaDB-cll-lve -- Server version: 10.6.12-MariaDB-cll-lve
-- PHP Version: 7.2.34
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */; /*!40101 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */; --
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -- Database: `u987021215_cms`
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; --
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; CREATE DATABASE IF NOT EXISTS `u987021215_cms` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; USE `u987021215_cms`;
-- --------------------------------------------------------
-- --
-- Table structure for table `edu` -- Table structure for table `edu`
-- --
DROP TABLE IF EXISTS `edu`; DROP TABLE IF EXISTS `edu`;
/*!40101 SET @saved_cs_client = @@character_set_client */; CREATE TABLE IF NOT EXISTS `edu` (
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `edu` (
`ID` int(11) NOT NULL AUTO_INCREMENT, `ID` int(11) NOT NULL AUTO_INCREMENT,
`startPeriod` date NOT NULL, `startPeriod` date NOT NULL,
`endPeriod` date NOT NULL, `endPeriod` date NOT NULL,
`grade` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL, `grade` varchar(20) NOT NULL,
`course` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL, `course` varchar(150) NOT NULL,
PRIMARY KEY (`ID`) PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Dumping data for table `edu` -- Dumping data for table `edu`
-- --
LOCK TABLES `edu` WRITE; INSERT INTO `edu` (`ID`, `startPeriod`, `endPeriod`, `grade`, `course`) VALUES
/*!40000 ALTER TABLE `edu` DISABLE KEYS */; (1, '2016-09-01', '2018-07-01', 'D*D*D*', 'Chelmsford College - BTEC Level 3 in IT'),
INSERT INTO `edu` (`ID`, `startPeriod`, `endPeriod`, `grade`, `course`) VALUES (1,'2016-09-01','2018-07-01','D*D*D*','Chelmsford College - BTEC Level 3 in IT'), (2, '2018-09-10', '2022-07-20', '2(i)', 'University of Sussex - Computer Science and AI with a placement year'),
(2,'2018-09-10','2022-07-20','2(i)','University of Sussex - Computer Science and AI with a placement year'), (11, '2022-09-26', '2023-08-25', 'Not completed yet', 'University of Nottingham - Computer Sciene (Artificial Intelligence)');
(11,'2022-09-26','2024-08-25','Not completed yet','University of Nottingham - Computer Sciene (Artificial Intelligence)');
/*!40000 ALTER TABLE `edu` ENABLE KEYS */; -- --------------------------------------------------------
UNLOCK TABLES;
-- --
-- Table structure for table `projects` -- Table structure for table `projects`
-- --
DROP TABLE IF EXISTS `projects`; DROP TABLE IF EXISTS `projects`;
/*!40101 SET @saved_cs_client = @@character_set_client */; CREATE TABLE IF NOT EXISTS `projects` (
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `projects` (
`ID` int(11) NOT NULL AUTO_INCREMENT, `ID` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL, `title` varchar(100) NOT NULL,
`date` date NOT NULL,
`isMainProject` tinyint(1) NOT NULL, `isMainProject` tinyint(1) NOT NULL,
`information` text COLLATE utf8mb4_unicode_ci NOT NULL, `information` text NOT NULL,
`imgLocation` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL, `imgLocation` varchar(200) NOT NULL DEFAULT '',
`projectLink` text COLLATE utf8mb4_unicode_ci NOT NULL, `projectLink` text NOT NULL DEFAULT '',
`githubLink` text COLLATE utf8mb4_unicode_ci NOT NULL, `gitLink` text NOT NULL,
PRIMARY KEY (`ID`) PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ) ENGINE=InnoDB AUTO_INCREMENT=73 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Dumping data for table `projects` -- Dumping data for table `projects`
-- --
LOCK TABLES `projects` WRITE; INSERT INTO `projects` (`ID`, `title`, `isMainProject`, `information`, `imgLocation`, `projectLink`, `gitLink`) VALUES
/*!40000 ALTER TABLE `projects` DISABLE KEYS */; (57, 'Money Tabs', 0, 'This is an app to keep a track of who owes whom and how much they owe per transaction. Soon group tab functionality will be added to keep a track of a group goal such as payment towards a holiday etc.', '', 'N/A', 'https://github.com/rodude123/MoneyTabs'),
INSERT INTO `projects` (`ID`, `title`, `date`, `isMainProject`, `information`, `imgLocation`, `projectLink`, `githubLink`) VALUES (1,'Money Tabs','2021-09-28',1,'This is a web app that should allow users to add friends as tabs so that they can easily manage, who owes them and who they owe.','N/A','N/A','https://github.com/rodude123/money-tabs'), (59, 'GyroTennis', 1, 'Do you like the Wii? Would you rather launch your iPhone across the room than a controller? Then is this the game for you! Now you can play motion-control tennis using your phone as the controller! (P.S. Any damage done to your phone is your fault)', '../imgs/projects/gyroTennis.png', 'https://devpost.com/software/gyrotennis', 'https://github.com/rodude123/HackNotts23'),
(2,'Money Tabs','2021-09-28',0,'This is a web app that should allow users to add friends as tabs so that they can easily manage, who owes them and who they owe.','N/A','N/A','https://github.com/rodude123/money-tabs'); (60, 'This Portfolio', 0, 'Well, it took a while to get it completed but got there in the end. This website is built using HTML, CSS, JS and the Slim framework with PHP, which means no frontend frameworks. Personally, I think it looks great, but I\'ll leave that to you.', '../imgs/projects/portfolio.png', 'https://rohitpai.co.uk', 'https://gitea.rohitpai.co.uk/rodude123/my-portfolio'),
/*!40000 ALTER TABLE `projects` ENABLE KEYS */; (69, 'Linux Wallpaper Changer', 0, 'A very simple wallpaper changer script for a Linux-based distribution running KDE and XFCE at the moment. It allows you to change the wallpaper by running the shell script and then allows you to save it to your pictures directory so that you can reuse it later at random. You can even add it to your crontab or create a system timer so that you can a change every \"X\" e.g. every 30 minutes', '../imgs/projects/Landscapes-10.png', 'N/A', 'https://github.com/rodude123/wallpaper-changer'),
UNLOCK TABLES; (70, 'Fixing Windows', 0, 'Made for the 2020 Global Game Jam, it\'s a game where you have to fix your windows computer as well as fight off the zombie infestation. Made using Gadot and GD script', '../imgs/projects/fixing windows.png', 'N/A', 'https://github.com/smilo7/fixing_windows_GGJ'),
(71, 'Magic the Gathering Card Image Downloader', 0, 'Automates the download process of card images for magic the gathering so that it can be proxied into a deck', '', 'N/A', 'https://gitea.rohitpai.co.uk/rodude123/magic-download-images'),
(72, 'Fiinal Year Project', 0, 'This was my final year project for my undergrad degree. I created a FPS AI system for Unity where you could add in AI to your own FPS game. ', '../imgs/projects/developerTesting1.png', 'N/A', 'https://github.com/rodude123/configurable-FPS-AI');
-- --------------------------------------------------------
-- --
-- Table structure for table `users` -- Table structure for table `users`
-- --
DROP TABLE IF EXISTS `users`; DROP TABLE IF EXISTS `users`;
/*!40101 SET @saved_cs_client = @@character_set_client */; CREATE TABLE IF NOT EXISTS `users` (
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `users` (
`ID` int(11) NOT NULL AUTO_INCREMENT, `ID` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `username` varchar(50) DEFAULT NULL,
`email` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `email` varchar(200) DEFAULT NULL,
`password` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `password` varchar(500) DEFAULT NULL,
`mfaSecret` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `mfaSecret` varchar(500) DEFAULT NULL,
`resetCode` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `resetCode` varchar(200) DEFAULT NULL,
PRIMARY KEY (`ID`) PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Dumping data for table `users` -- Dumping data for table `users`
-- --
LOCK TABLES `users` WRITE; INSERT INTO `users` (`ID`, `username`, `email`, `password`, `mfaSecret`, `resetCode`) VALUES
/*!40000 ALTER TABLE `users` DISABLE KEYS */; (1, 'rodude123', 'rodude123@gmail.com', '$2y$10$oRtVHNLEnMtwEzgGAScALeISUP28HVk.GvwH8naFZZrQKu0OF9xu2', '0', '0');
INSERT INTO `users` (`ID`, `username`, `email`, `password`, `mfaSecret`, `resetCode`) VALUES (1,'rodude123','rodude123@gmail.com','$2y$10$oRtVHNLEnMtwEzgGAScALeISUP28HVk.GvwH8naFZZrQKu0OF9xu2','0','0');
/*!40000 ALTER TABLE `users` ENABLE KEYS */; -- --------------------------------------------------------
UNLOCK TABLES;
-- --
-- Table structure for table `work` -- Table structure for table `work`
-- --
DROP TABLE IF EXISTS `work`; DROP TABLE IF EXISTS `work`;
/*!40101 SET @saved_cs_client = @@character_set_client */; CREATE TABLE IF NOT EXISTS `work` (
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `work` (
`ID` int(11) NOT NULL AUTO_INCREMENT, `ID` int(11) NOT NULL AUTO_INCREMENT,
`startPeriod` date NOT NULL, `startPeriod` date NOT NULL,
`endPeriod` date DEFAULT NULL, `endPeriod` date DEFAULT NULL,
`companyName` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL, `companyName` varchar(30) NOT NULL,
`area` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL, `area` varchar(30) NOT NULL,
`title` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL, `title` varchar(50) NOT NULL,
PRIMARY KEY (`ID`) PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
-- --
-- Dumping data for table `work` -- Dumping data for table `work`
-- --
LOCK TABLES `work` WRITE; INSERT INTO `work` (`ID`, `startPeriod`, `endPeriod`, `companyName`, `area`, `title`) VALUES
/*!40000 ALTER TABLE `work` DISABLE KEYS */; (1, '2016-09-01', '2017-08-31', 'Co-op', 'Billericay', 'Retail Assistant'),
INSERT INTO `work` (`ID`, `startPeriod`, `endPeriod`, `companyName`, `area`, `title`) VALUES (1,'2016-09-01','2017-08-31','Co-op','Billericay','Retail Assistant'), (2, '2019-07-01', '2019-08-31', 'Cerebriu', 'Copenhagen', 'Student Intern'),
(2,'2019-07-01','2019-08-31','Cerebriu','Copenhagen','Student Intern'), (3, '2020-09-01', '2021-07-30', 'Cerebriu', 'Copenhagen', 'Intern Consultant');
(3,'2020-09-01','2021-07-30','Cerebriu','Copenhagen','Intern Consultant'); COMMIT;
/*!40000 ALTER TABLE `work` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2022-12-24 18:37:29

View File

@ -83,7 +83,7 @@ a.btn:hover, form input[type="submit"]:hover {
} }
a.btnPrimary, form input[type="submit"] { a.btnPrimary, form input[type="submit"] {
background: var(--primaryDefault); background-color: var(--primaryDefault);
cursor: pointer; cursor: pointer;
} }

View File

@ -3,7 +3,7 @@ let textareaLoaded = false;
document.addEventListener('DOMContentLoaded', () => document.addEventListener('DOMContentLoaded', () =>
{ {
// check if the user is logged in, if not redirect to log in // check if the userData is logged in, if not redirect to log in
fetch('/api/user/isLoggedIn').then(res => fetch('/api/user/isLoggedIn').then(res =>
{ {
if (!res.ok) if (!res.ok)
@ -654,7 +654,7 @@ function updateProjectItem(id, e)
{ {
window.location.href = "./"; window.location.href = "./";
return; return;
} }ujh
document.querySelector(`#projError${id}`).classList.remove("hidden"); document.querySelector(`#projError${id}`).classList.remove("hidden");
document.querySelector(`#projError${id} div`).innerHTML = updatedProjectImage.error; document.querySelector(`#projError${id} div`).innerHTML = updatedProjectImage.error;

View File

@ -1,7 +1,7 @@
document.addEventListener("DOMContentLoaded", _ => document.addEventListener("DOMContentLoaded", _ =>
{ {
// check if the user is logged in and if so load the editor // check if the userData is logged in and if so load the editor
fetch("/api/user/isLoggedIn").then(res => fetch("/api/user/isLoggedIn").then(res =>
{ {
if (res.ok) if (res.ok)

View File

@ -29,7 +29,7 @@
<li><a href="#curriculumVitae" class="textShadow"><span>&lt;</span>cv<span>&gt;</span></a></li> <li><a href="#curriculumVitae" class="textShadow"><span>&lt;</span>cv<span>&gt;</span></a></li>
<li><a href="#projects" class="textShadow"><span>&lt;</span>projects<span>&gt;</span></a></li> <li><a href="#projects" class="textShadow"><span>&lt;</span>projects<span>&gt;</span></a></li>
<li><a href="#contact" class="textShadow"><span>&lt;</span>contact<span>&gt;</span></a></li> <li><a href="#contact" class="textShadow"><span>&lt;</span>contact<span>&gt;</span></a></li>
<li><a href="#" class="textShadow"><span>&lt;</span>blog<span>&gt;</span></a></li> <li><a href="/blog" class="textShadow"><span>&lt;</span>blog<span>&gt;</span></a></li>
</ul> </ul>
</nav> </nav>
<header> <header>

View File

@ -133,7 +133,7 @@ function getProjectData()
</div> </div>
<div> <div>
<a href="${(json[i]["projectLink"] === "N/A") ? "#" : json[i]["projectLink"]}" class="btn btnPrimary boxShadowIn boxShadowOut"${(json[i]["projectLink"] === "N/A") ? "disabled=\"disabled\"" : ""}>View Project</a> <a href="${(json[i]["projectLink"] === "N/A") ? "#" : json[i]["projectLink"]}" class="btn btnPrimary boxShadowIn boxShadowOut"${(json[i]["projectLink"] === "N/A") ? "disabled=\"disabled\"" : ""}>View Project</a>
<a href="${(json[i]["githubLink"] === "N/A") ? "#" : json[i]["gitubLink"]}" class="btn btnOutline boxShadowIn boxShadowOut">${(json[i]["githubLink"] === "N/A") ? "disabled=\"disabled\"" : ""}Git</a> <a href="${(json[i]["githubLink"] === "N/A") ? "#" : json[i]["gitLink"]}" class="btn btnOutline boxShadowIn boxShadowOut">${(json[i]["githubLink"] === "N/A") ? "disabled=\"disabled\"" : ""}Git</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -62,7 +62,7 @@ function getProjectData()
</div> </div>
<div> <div>
<a href="${(item["projectLink"] === "N/A") ? "#" : item["projectLink"]}" class="btn btnPrimary boxShadowIn boxShadowOut"${(item["projectLink"] === "N/A") ? "disabled=\"disabled\"" : ""}>View Project</a> <a href="${(item["projectLink"] === "N/A") ? "#" : item["projectLink"]}" class="btn btnPrimary boxShadowIn boxShadowOut"${(item["projectLink"] === "N/A") ? "disabled=\"disabled\"" : ""}>View Project</a>
<a href="${(item["githubLink"] === "N/A") ? "#" : item["gitubLink"]}" class="btn btnOutline boxShadowIn boxShadowOut">${(item["githubLink"] === "N/A") ? "disabled=\"disabled\"" : ""}Git</a> <a href="${(item["githubLink"] === "N/A") ? "#" : item["gitLink"]}" class="btn btnOutline boxShadowIn boxShadowOut">${(item["githubLink"] === "N/A") ? "disabled=\"disabled\"" : ""}Git</a>
</div> </div>
</div> </div>
</div> </div>

Binary file not shown.

View File

@ -29,7 +29,7 @@
<li><a href="/#curriculumVitae" class="textShadow"><span>&lt;</span>cv<span>&gt;</span></a></li> <li><a href="/#curriculumVitae" class="textShadow"><span>&lt;</span>cv<span>&gt;</span></a></li>
<li><a href="#allProjects" class="textShadow active"><span>&lt;</span>projects<span>&gt;</span></a></li> <li><a href="#allProjects" class="textShadow active"><span>&lt;</span>projects<span>&gt;</span></a></li>
<li><a href="/#contact" class="textShadow"><span>&lt;</span>contact<span>&gt;</span></a></li> <li><a href="/#contact" class="textShadow"><span>&lt;</span>contact<span>&gt;</span></a></li>
<li><a href="#" class="textShadow"><span>&lt;</span>blog<span>&gt;</span></a></li> <li><a href="/blog" class="textShadow"><span>&lt;</span>blog<span>&gt;</span></a></li>
</ul> </ul>
</nav> </nav>