From 5a5471da5d8bd376188b7204da75d2cd438a1e3b Mon Sep 17 00:00:00 2001 From: Josh Ashton Date: Sun, 30 Mar 2025 20:37:28 -0600 Subject: [PATCH] implemented mass creation via csv, bug fixes --- admin.php | 30 ++++++++------ components/foot.php | 21 +++++++++- components/nav.php | 2 +- css/base.css | 2 +- functions/account_functions.php | 8 +--- functions/admin_functions.php | 32 ++++++++++++++- functions/functions.php | 31 ++++++++++++--- functions/init.php | 4 +- test.csv | 2 + user.php | 6 ++- vintagecoding.net.md | 69 +++++++++++++++++++++++++++++++++ 11 files changed, 176 insertions(+), 31 deletions(-) create mode 100644 test.csv create mode 100644 vintagecoding.net.md diff --git a/admin.php b/admin.php index bf85306..9db80fa 100644 --- a/admin.php +++ b/admin.php @@ -11,19 +11,25 @@ else if ($_COOKIE['role_id'] >= 3) include_once 'functions/admin_functions.php'; -if (isset($_POST['action']) && isset($_POST['form_id'])) { - switch ($_POST['action']) { - case 'delete': - if ($_POST['form_id'] == 'users') - foreach ($_POST['selected_users'] as $id) - delete_account($id); - else if ($_POST['form_id'] == 'articles') - foreach ($_POST['selected_articles'] as $id) - delete_article($id); - break; +if (isset($_POST['action']) && isset($_POST['form_id']) || isset($_FILES['csv'])) { + if (!empty($_FILES['csv']['name'])) { + upload($_FILES['csv'], $_ENV['UPLOAD_TMP_FQ_PATH'], 'new_users'); + create_users_from_csv($_ENV['UPLOAD_TMP_FQ_PATH'] . 'new_users.csv'); + delete_file($_ENV['UPLOAD_TMP_FQ_PATH'] . 'new_users.csv'); + } else { + switch ($_POST['action']) { + case 'delete': + if ($_POST['form_id'] == 'users') + foreach ($_POST['selected_users'] as $id) + delete_account($id); + else if ($_POST['form_id'] == 'articles') + foreach ($_POST['selected_articles'] as $id) + delete_article($id); + break; - case 'view': - header('Location: user.php?action=view&user_id=' . $_POST['selected_users'][0]); + case 'view': + header('Location: user.php?action=view&user_id=' . $_POST['selected_users'][0]); + } } } diff --git a/components/foot.php b/components/foot.php index 165ddd8..98d0e19 100644 --- a/components/foot.php +++ b/components/foot.php @@ -2,7 +2,8 @@ diff --git a/components/nav.php b/components/nav.php index 1d6e7ff..bbf7315 100644 --- a/components/nav.php +++ b/components/nav.php @@ -11,7 +11,7 @@ $nav = ' if (isset($_COOKIE['role_id']) && $_COOKIE['role_id'] <= 2) { $nav .= ' -
  • Admin
  • +
  • Admin
  • '; } diff --git a/css/base.css b/css/base.css index 5d0ee78..213a392 100644 --- a/css/base.css +++ b/css/base.css @@ -256,7 +256,7 @@ table tr td label { } .narrow { - width: 40%; + width: 20%; } .tag { diff --git a/functions/account_functions.php b/functions/account_functions.php index d12b0af..583927d 100644 --- a/functions/account_functions.php +++ b/functions/account_functions.php @@ -153,7 +153,7 @@ function signup_form($error_msg = '') return $form; } -function signup($username, $email, $password, $verify_password, $role_id, $upload = null, $x = null, $y = null, $crop_width = null) +function create_user($username, $email, $password, $verify_password, $role_id, $upload = null, $x = null, $y = null, $crop_width = null) { if ($password != $verify_password) { $error_msg = ' @@ -184,10 +184,6 @@ function signup($username, $email, $password, $verify_password, $role_id, $uploa $stmt = 'INSERT INTO user (user_id, username, email, password_hash, role_id' . (!empty($target) ? ', profile_picture' : '') . ') VALUES (' . $id . ', "' . $username . '", "' . $email . '", "' . $password_hash . '", ' . $role_id . (!empty($target) ? ', "' . $target . '"' : '') . ');'; exec_statement($stmt, 0); - - login($username, $password, false); - - return true; } function profile_cropper() @@ -448,7 +444,7 @@ function delete_account($user_id, $password = null, $verify_password = null) exec_statement($stmt, 1); logout(); } else if ($_COOKIE['role_id'] < 3) { - $query = 'SELECT user_id FROM user WHERE user_id = ' . $user_id . ';'; + $query = 'SELECT user_id, profile_picture FROM user WHERE user_id = ' . $user_id . ';'; $user = query_one_result($query); if ($user['user_id'] == 2025) { diff --git a/functions/admin_functions.php b/functions/admin_functions.php index 807487e..2ca091d 100644 --- a/functions/admin_functions.php +++ b/functions/admin_functions.php @@ -1,8 +1,32 @@ View Articles
    -
    +
    + + + + No file selected. +
    diff --git a/functions/functions.php b/functions/functions.php index d384291..51deb8f 100644 --- a/functions/functions.php +++ b/functions/functions.php @@ -41,19 +41,27 @@ function upload($input, $dest_dir, $filename = null) case 'png': case 'jpg': case 'jpeg': - if (check_image_upload($dest_dir, $filetype, $input)) { + if (check_image_upload($dest_dir, $filetype, $input)) move_uploaded_file($input['tmp_name'], $dest_dir . ($filename ? $filename . '.' . $filetype : $input['name'])); - if ($filename) - return basename($filename . '.' . $filetype); - else - return basename($input['name'] . '.' . $filetype); - } else + else return ''; break; + case 'csv': + if (check_csv_upload($input)) + move_uploaded_file($input['tmp_name'], $dest_dir . ($filename ? $filename . '.' . $filetype : $input['name'])); + else + return ''; + + break; default: # code... break; } + + if ($filename) + return basename($filename . '.' . $filetype); + else + return basename($input['name'] . '.' . $filetype); } function crop_image($img_path, $x, $y, $height, $width) @@ -114,11 +122,22 @@ function read_file_one_string($file_path) return $string; } +function read_file($file_path) +{ + $fs = fopen($file_path, 'r'); + return $fs; +} + function check_image_upload($target, $filetype, $image) { return true; } +function check_csv_upload($target) +{ + return true; +} + function pretty_dump($arr) { echo ' diff --git a/functions/init.php b/functions/init.php index f805cd0..eb46387 100644 --- a/functions/init.php +++ b/functions/init.php @@ -20,5 +20,7 @@ if ($_SESSION['initialized'] && isset($_POST['theme'])) { unset($_POST['theme']); } -if (isset($_COOKIE['user_id'])) +if (isset($_COOKIE['user_id'])) { exec_statement('UPDATE user SET is_active = true WHERE user_id = ' . $_COOKIE['user_id'] . ';', 1); + exec_statement('UPDATE user SET last_active = CURRENT_TIMESTAMP WHERE user_id = ' . $_COOKIE['user_id'] . ';', 1); +} diff --git a/test.csv b/test.csv new file mode 100644 index 0000000..36df611 --- /dev/null +++ b/test.csv @@ -0,0 +1,2 @@ +jashton,jashton@slcpl.org,changeme,2 +violet,violetash501@gmail.com,something,3 diff --git a/user.php b/user.php index afd8ffc..2836eb0 100644 --- a/user.php +++ b/user.php @@ -9,7 +9,7 @@ $msg = ''; if (isset($_POST['form_id'])) { switch ($_POST['form_id']) { case 'signup_form': - $msg = signup( + $msg = create_user( $_POST['username'], $_POST['email'], $_POST['password'], @@ -21,8 +21,10 @@ if (isset($_POST['form_id'])) { (!empty($_POST['crop_width']) ? $_POST['crop_width'] : '') ); - if ($msg === true) + if ($msg === true) { + login($_POST['username'], $_POST['password'], false); header('Location: user.php?action=view&user_id=' . $_COOKIE['user_id']); + } break; diff --git a/vintagecoding.net.md b/vintagecoding.net.md new file mode 100644 index 0000000..9dd4190 --- /dev/null +++ b/vintagecoding.net.md @@ -0,0 +1,69 @@ +### vintagecoding.net + +- [x] Ensure a consistent design & UX aesthetic --- v0.1.0 + - [ ] Sensible CSS class names for a modular styling approach --- v0.2.0 + +- [ ] Convert db_functions.php queries/statements into prepared SQL for protection against SQL injection --- v0.2.0 + +- [ ] Email Handler: + - [ ] Email users subscribed to author or tag whenever a new article is posted. --- v0.3.0 + - [ ] Email me whenever a user requests a role change. --- v0.3.0 + +#### Systems Interfaces +- [x] Admin panel (manage articles & accounts) --- v0.2.0 + +- [ ] Implement a notification modal system for handling error and success messages. --- v0.2.0 + +- [ ] Accounts: + #### Account CRUD --- account_functions.php + - [x] Self Auth Level (a simple get, though should always get from the DB since that'll reflect the latest changes.) --- v0.1.0 + - [x] Modify Self ---v0.1.0 + - [x] Delete Self (user opt-out of the deletion of articles they've written.) --- v0.1.0 + - [x] Create User (either new user or admin or higher auth) --- v0.1.0 + - [ ] Implement OAuth accounts --- v0.2.0 + - [x] Login --- v0.1.0 + - [ ] Implement OAuth 2.0 accounts --- v0.2.0 + - [x] Modify User (requires auth) --- v0.2.0 + - [x] Delete User --- v0.2.0 + - [x] Get User Admin (requires auth, shows limited information for privacy) --- v0.2.0 + - [x] Get Users (requires auth) --- v0.2.0 + - [x] Create Users (requires auth) --- v0.2.0 + - [x] Delete Users --- v0.2.0 + - [ ] Get User (for public facing account page) --- v0.2.0 + + #### Analytics on Accounts (requires auth) --- account_analytic_functions.php + - [ ] Get Users by Creation --- v0.3.0 + - [ ] Get Users by Articles Written --- v0.3.0 + - [ ] Get Users by Last Login --- v0.3.0 + - [ ] Get Users by Is Active --- v0.3.0 + + #### Account Systems Interfaces + - [x] Sign Up & Login Form --- v0.1.0 + - [x] Account Settings (requires login, self) --- v0.1.0 + - [ ] Account Page (of each user, hidden by default) --- v0.2.0 + - [ ] Allow for user customization of their account page (colors, layout, maybe even let them have their own CSS file to make changes) --- v0.2.0 + +- [ ] Articles: + #### Article CRUD --- article_functions.php + - [x] Create Article (requires contributor or higher) --- v0.1.0 + - [x] Prompt for tags + - [x] Use account information to populate author information + - [x] Get Article by ID --- v0.1.0 + - [x] Get Articles by ID --- v0.1.0 + - [x] Get Articles by Recency --- v0.1.0 + - [x] Get Articles by Tag --- v0.1.0 + - [x] Delete Article by ID --- v0.1.0 + - [x] Delete Articles by Author (for account deletion) --- v0.1.0 + - [ ] Draft/unpublished status --- v0.2.0 + - [ ] Update Article by ID (required to be the author updating) --- v0.2.0 + - [ ] Get Articles by Author --- v0.2.0 + - [ ] Sort / filter system --- v0.2.0 + + #### Article System Interface + - [ ] Convert articles.php layout to a grid, to display a left hand column with a search/filtering system or table of contents. --- v0.2.0 + - [ ] Advanced markdown editor or upload markdown, with media upload support (images & code files, requires contributor or higher auth) --- v0.3.0 + + ### Unplanned but implemented + - [ ] Vim motions for navigation + - [ ] Terminal access? security challenge. + - Image cropper. 12 hoursish, learned a lot though. Opted not to use cropper.js or cropper, wanted the challenge. Needs to be refactored/rewritten. --- v0.1.0 @ 29/3/2025