commit da4133455749ad995882cc4ca122c10c6c51d32d
parent 1b03f4e12bf00ea93e0c66e560da667c4e40276f
Author: JayVii <jayvii[AT]posteo[DOT]de>
Date: Fri, 25 Oct 2024 18:06:28 +0200
feat: implement rudimentary auth process
Diffstat:
11 files changed, 281 insertions(+), 30 deletions(-)
diff --git a/config/config.php b/config/config.php
@@ -0,0 +1,3 @@
+<?php
+
+$GLOBALS["pw_salt"] = "set_a_proper_salt";
diff --git a/config/i18n.php b/config/i18n.php
@@ -14,6 +14,10 @@ if ($lang == "en") {
$GLOBALS["i18n_edit"] = "Edit note";
$GLOBALS["i18n_new"] = "New note";
$GLOBALS["i18n_list"] = "List notes";
+ $GLOBALS["i18n_login"] = "Login";
+ $GLOBALS["i18n_user"] = "Username";
+ $GLOBALS["i18n_pass"] = "Password";
+ $GLOBALS["i18n_logout"] = "Logout";
}
diff --git a/index.php b/index.php
@@ -8,7 +8,6 @@
if (!array_key_exists("action", $_POST)) {
$_POST["action"] = "list";
}
- $_POST["user"] = "test_user";
/* Load library functions */
foreach (glob("./lib/*.php") as $lib) {
@@ -20,13 +19,31 @@
include($conf);
}
- /* Gather POST input */
+ /* Gather POST input and validate if necessary */
$action = gather_post("action");
- $category = gather_post("category");
- $filename = gather_post("filename");
+ $category = validate_input_string(gather_post("category"));
+ $filename = validate_input_string(gather_post("filename"));
$filepath_t1 = gather_post("filepath_t1");
$content = gather_post("content");
- $user = gather_post("user");
+ $GLOBALS["user"] = validate_input_string(gather_post("user"));
+ $pass = gather_post("pass");
+ $GLOBALS["token"] = gather_post("token");
+
+ /* if password is given, but token is not, create the token! */
+ if ($GLOBALS["token"] == "") {
+ $GLOBALS["token"] = create_password_hash($pass);
+ }
+
+ /* Check authentification of user */
+ $auth = auth_user($GLOBALS["user"], $token);
+ if ($auth !== true) {
+ $action = "login";
+ }
+
+ /* ensure the given filename has a valid extension */
+ if (count(preg_grep("/\.txt$/", array($filename), PREG_GREP_INVERT)) > 0) {
+ $filename = $filename . ".txt";
+ }
?>
@@ -43,6 +60,13 @@
<body>
+<?php
+
+ /* Only show Header if we are not at login */
+ if ($action != "login") {
+
+?>
+
<header>
<!-- Buttons -->
<nav>
@@ -53,7 +77,13 @@
id="user"
name="user"
type="hidden"
- value="<?php echo $user; ?>"
+ value="<?php echo $GLOBALS["user"]; ?>"
+ >
+ <input
+ id="token"
+ name="token"
+ type="hidden"
+ value="<?php echo $GLOBALS["token"]; ?>"
>
<input
id="category"
@@ -78,6 +108,37 @@
value="<?php echo $GLOBALS["i18n_new"]; ?>"
>
</form>
+ <!-- Logout-Action -->
+ <form action="/" target="_self" method="post">
+ <input
+ id="user"
+ name="user"
+ type="hidden"
+ value=""
+ >
+ <input
+ id="pass"
+ name="pass"
+ type="hidden"
+ value=""
+ >
+ <input
+ id="token"
+ name="token"
+ type="hidden"
+ value=""
+ >
+ <input
+ id="action"
+ name="action"
+ type="hidden"
+ value="list"
+ >
+ <input
+ type="submit"
+ value="<?php echo $GLOBALS["i18n_logout"]; ?>"
+ >
+ </form>
</nav>
<!-- Headline -->
@@ -89,7 +150,13 @@
id="user"
name="user"
type="hidden"
- value="<?php echo $user; ?>"
+ value="<?php echo $GLOBALS["user"]; ?>"
+ >
+ <input
+ id="token"
+ name="token"
+ type="hidden"
+ value="<?php echo $GLOBALS["token"]; ?>"
>
<input
id="action"
@@ -104,16 +171,24 @@
</form>
<?php
- /* Fetch all categories of the user */
- $categories_path = glob("./data/" . $user . "/*");
- foreach ($categories_path as $category_path) {
+ /* Fetch all categories of the user */
+ $categories_path = glob("./data/" . $GLOBALS["user"] . "/*");
+ foreach ($categories_path as $category_path) {
+
+ if (count(glob($category_path . "/" . "*.txt")) > 0) {
?>
<form action="/" target="_self" method="post">
<input
id="user"
name="user"
type="hidden"
- value="<?php echo $user; ?>"
+ value="<?php echo $GLOBALS["user"]; ?>"
+ >
+ <input
+ id="token"
+ name="token"
+ type="hidden"
+ value="<?php echo $GLOBALS["token"]; ?>"
>
<input
id="category"
@@ -133,31 +208,39 @@
>
</form>
<?php
- } // foreach-loop
+ } // if-statement
+ } // foreach-loop
?>
</header>
<?php
+ } // if-statement
+
+ /* Login action */
+ if ($action == "login") {
+ show_login_form("list");
+ die();
+ }
+
/* Listing action */
if ($action == "list") {
/* if no category is given, list all. otherwise only show given */
- if (!is_null($category)) {
+ if ($category != "") {
$categories_path = array(
- "./data/" . $user . "/" . $category
+ "./data/" . $GLOBALS["user"] . "/" . $category
);
}
foreach ($categories_path as $category_path) {
- list_notes($user, basename($category_path));
+ list_notes(basename($category_path));
}
}
/* Edit action */
if ($action == "edit") {
edit_note(
- $user,
$category,
$filename,
$filepath_t1,
@@ -170,7 +253,6 @@
/* Show action */
if ($action == "show") {
show_note(
- $user,
$category,
$filename
);
diff --git a/lib/edit.php b/lib/edit.php
@@ -1,7 +1,6 @@
<?php
function edit_note(
- string $user,
string $category,
string $filename,
string $filepath_t1,
@@ -10,7 +9,7 @@ function edit_note(
/* Write note as if it was completely new */
$written = write_note(
- $user,
+ $GLOBALS["user"],
$category,
$filename,
$content
@@ -22,12 +21,12 @@ function edit_note(
}
/* construct new filepath */
- $filepath_t0 = $user . "/" . $category . "/" . $filename;
+ $filepath_t0 = $category . "/" . $filename;
/* if old and new filepaths differ, the file was likely renamed.
* delete the old one and exit immediately */
if ($filepath_t1 != $filepath_t0) {
- return unlink("./data/" . $filepath_t1);
+ return unlink("./data/" . $GLOBALS["user"] . "/" . $filepath_t1);
}
/* if all actions went through, return "true" */
diff --git a/lib/helpers.php b/lib/helpers.php
@@ -5,10 +5,20 @@ function gather_post(string $key) {
if (array_key_exists($key, $_POST)) {
return $_POST[$key];
} else {
- return null;
+ return "";
}
}
+function validate_input_string(string $in) {
+ /* Only allows alphanumeric characters and any of "-_." */
+ $out = preg_replace(
+ "/[^A-Za-z0-9\-\_\.]/",
+ "_",
+ $in
+ );
+ return $out;
+}
+
function sort_by_time(array $a, array $b) {
// sort from oldest to newest (reversed)
return $b["time"] - $a["time"];
diff --git a/lib/list.php b/lib/list.php
@@ -1,17 +1,16 @@
<?php
function list_notes(
- string $user,
string $category
) {
/* Create full path name */
- $dirpath = "./data/" . $user . "/" . $category;
+ $dirpath = "./data/" . $GLOBALS["user"] . "/" . $category;
/* list all available notes */
$filematches = glob($dirpath . "/" . "*.txt");
- if ($filematches !== false) {
+ if (count($filematches) > 0) {
/* Gather each file next to its edit time stamp */
$filenames = array();
@@ -80,7 +79,13 @@ function list_notes(
id="user"
name="user"
type="hidden"
- value="<?php echo $user; ?>"
+ value="<?php echo $GLOBALS["user"]; ?>"
+ >
+ <input
+ id="token"
+ name="token"
+ type="hidden"
+ value="<?php echo $GLOBALS["token"]; ?>"
>
<input
id="category"
diff --git a/lib/login.php b/lib/login.php
@@ -0,0 +1,26 @@
+<?php
+
+function show_login_form(string $target) {
+
+?>
+
+<form action="/" target="_self" method="post">
+ <label for="user"><?php echo $GLOBALS["i18n_user"]; ?></label>
+ <input id="user" name="user" type="text">
+ <label for="pass"><?php echo $GLOBALS["i18n_pass"]; ?></label>
+ <input id="pass" name="pass" type="password">
+ <input
+ id="action"
+ name="action"
+ type="hidden"
+ value="<?php echo $target; ?>"
+ >
+ <input type="submit" value="<?php echo $GLOBALS["i18n_login"]; ?>">
+</form>
+
+<?php
+
+} // function
+
+?>
+
diff --git a/lib/show.php b/lib/show.php
@@ -1,13 +1,12 @@
<?php
function show_note(
- string $user,
string $category,
string $filename
) {
/* Read Note: if it does not exist yet, use empty string */
- $content = read_note($user, $category, $filename);
+ $content = read_note($GLOBALS["user"], $category, $filename);
?>
@@ -33,7 +32,7 @@ function show_note(
id="filepath_t1"
name="filepath_t1"
type="hidden"
- value="<?php echo $user . "/" . $category . "/" . $filename; ?>"
+ value="<?php echo $category . "/" . $filename; ?>"
>
<input
id="action"
@@ -41,6 +40,18 @@ function show_note(
type="hidden"
value="edit"
>
+ <input
+ id="user"
+ name="user"
+ type="hidden"
+ value="<?php echo $GLOBALS["user"]; ?>"
+ >
+ <input
+ id="token"
+ name="token"
+ type="hidden"
+ value="<?php echo $GLOBALS["token"]; ?>"
+ >
<input type="submit" value="<?php echo $GLOBALS["i18n_save"]; ?>">
</form>
diff --git a/lib/users.php b/lib/users.php
@@ -0,0 +1,93 @@
+<?php
+
+function create_password_hash(
+ string $pass
+) {
+
+ /* check if salt is set properly */
+ if (!array_key_exists("pw_salt", $GLOBALS)) {
+ exit("Your password salt was not set properly!");
+ }
+
+ /* Create hash from given password */
+ $token = hash("sha256", $pass . $GLOBALS["pw_salt"], false);
+
+ /* return resulting token */
+ return $token;
+}
+
+function auth_user(
+ string $user,
+ string $token
+) {
+
+ /* read token file of user */
+ $tokens_storage = file(
+ "./data/" . $user . "/.tokens",
+ FILE_IGNORE_NEW_LINES
+ );
+ if ($tokens_storage === false) {
+ $tokens_storage = array();
+ }
+
+ /* find any matches between given hash and tokens */
+ $matches = preg_grep(
+ "/" . $token . "/",
+ $tokens_storage
+ );
+
+ /* If matches between given hash and tokens were found, return "true" */
+ if (count($matches) > 0 && $matches !== false) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+function create_auth(
+ string $user,
+ string $pass
+) {
+
+ /* create hash from given password */
+ $token = create_password_hash($pass);
+
+ /* generate token path */
+ $user_path = "./data/" . $user;
+ $token_path = $user_path . "/.tokens";
+
+ /* Only create new auth, if no previous token file exists already */
+ if (file_exists($token_path)) {
+ exit("Token already exists! Use \"change_auth()\" instead!");
+ }
+
+ /* create user directory if it does not exist */
+ if (opendir($user_path) === false) {
+ mkdir(
+ $user_path, /* directory */
+ 0770, /* Permissions: rwxrwx--- */
+ true /* recursive */
+ );
+ }
+
+ /* create file-handle */
+ $file = fopen(
+ $token_path,
+ "w"
+ );
+
+ /* Write to file */
+ $bytes = fwrite(
+ $file,
+ $token
+ );
+
+ /* close file-hanle */
+ fclose($file);
+
+ /* return "true" on success and "false" otherwise */
+ return $bytes !== false;
+
+}
+
+?>
diff --git a/lib/write.php b/lib/write.php
@@ -12,7 +12,7 @@ function write_note(
$filepath = $dirpath . "/" . $filename;
/* create user directory if it does not exist */
- if (opendir($dirpath) !== false) {
+ if (opendir($dirpath) === false) {
mkdir(
$dirpath, /* directory */
0770, /* Permissions: rwxrwx--- */
diff --git a/misc/create_initial_user.php b/misc/create_initial_user.php
@@ -0,0 +1,18 @@
+<?php
+
+include("./lib/users.php");
+include("./config/config.php");
+
+$user = readline('Enter new username: ');
+$pass = readline('Enter new password: ');
+
+$success = create_auth($user, $pass);
+
+if ($success) {
+ echo "Account " . $user . " created successfully!" . PHP_EOL;
+} else {
+ exit("Account creation failed for some reason...");
+}
+
+?>
+