implemented mass creation via csv, bug fixes

This commit is contained in:
2025-03-30 20:37:28 -06:00
parent e6735a9a20
commit 5a5471da5d
11 changed files with 176 additions and 31 deletions
+7 -1
View File
@@ -11,7 +11,12 @@ else if ($_COOKIE['role_id'] >= 3)
include_once 'functions/admin_functions.php';
if (isset($_POST['action']) && isset($_POST['form_id'])) {
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')
@@ -26,6 +31,7 @@ if (isset($_POST['action']) && isset($_POST['form_id'])) {
header('Location: user.php?action=view&user_id=' . $_POST['selected_users'][0]);
}
}
}
if (isset($_GET['view'])) {
switch ($_GET['view']) {
+20 -1
View File
@@ -2,7 +2,8 @@
<footer>
<?php
if ($_SERVER['SCRIPT_NAME'] == '/user.php') {
function get_args_from_url()
{
$args = [];
$arr = explode('&', $_SERVER['QUERY_STRING']);
@@ -14,6 +15,12 @@
$args[$key] = $value;
}
return $args;
}
if ($_SERVER['SCRIPT_NAME'] == '/user.php') {
$args = get_args_from_url();
if (isset($args['action'])) {
if ($args['action'] == 'signup') {
echo '
@@ -26,6 +33,18 @@
}
}
}
if ($_SERVER['SCRIPT_NAME'] == '/admin.php') {
$args = get_args_from_url();
if (isset($args['view'])) {
if ($args['view'] == 'users') {
echo '
<script src="js/upload.js"></script>
';
}
}
}
?>
</footer>
+1 -1
View File
@@ -11,7 +11,7 @@ $nav = '
if (isset($_COOKIE['role_id']) && $_COOKIE['role_id'] <= 2) {
$nav .= '
<li><a href="/admin.php"' . ($current_page == '/admin.php' ? ' class="underline"' : '') . '>Admin</a></li>
<li><a href="/admin.php?view=users"' . ($current_page == '/admin.php' ? ' class="underline"' : '') . '>Admin</a></li>
';
}
+1 -1
View File
@@ -256,7 +256,7 @@ table tr td label {
}
.narrow {
width: 40%;
width: 20%;
}
.tag {
+2 -6
View File
@@ -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) {
+31 -1
View File
@@ -1,8 +1,32 @@
<?php
require_once 'db_functions.php';
require_once 'functions.php';
require_once 'account_functions.php';
require_once 'article_functions.php';
function create_users_from_csv($csv)
{
$csv = read_file($csv);
while ($record = fgets($csv)) {
$fields = explode(',', $record);
$username = $fields[0];
$email = $fields[1];
$password = $fields[2];
$role_id = $fields[3];
create_user(
$username,
$email,
$password,
$password,
$role_id,
);
}
}
function admin_create_user() {}
function admin_article_view()
{
$display = '
@@ -71,6 +95,7 @@ function admin_article_view()
return $display;
}
function admin_user_view()
{
$display = '
@@ -80,13 +105,18 @@ function admin_user_view()
<a href="admin.php?view=articles">View Articles</a>
</div>
<div class="line"></div>
<form method="post">
<form method="post" enctype="multipart/form-data">
<input type="hidden" name="form_id" value="users">
<div class="row">
<label for="delete" class="form_checkbox_container">Delete
<input type="radio" class="button" name="action" id="delete" value="delete">
<span class="checkmark"></span>
</label>
<label id="create_users_from_csv_label" for="create_users_from_csv" class="upload_button">Upload a CSV</label>
<input id="create_users_from_csv" class="file_input" name="csv" type="file" accept=".csv">
<small class="file_input_feedback">No file selected.</small>
<input type="submit" class="button narrow" value="Commit">
</div>
+24 -5
View File
@@ -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
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 '
+3 -1
View File
@@ -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);
}
+2
View File
@@ -0,0 +1,2 @@
jashton,jashton@slcpl.org,changeme,2
violet,violetash501@gmail.com,something,3
1 jashton jashton@slcpl.org changeme 2
2 violet violetash501@gmail.com something 3
+4 -2
View File
@@ -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;
+69
View File
@@ -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