This commit is contained in:
2026-02-20 20:10:46 -08:00
parent 27fb986f58
commit b7a78b7bb9
29 changed files with 999 additions and 33 deletions
@@ -0,0 +1,31 @@
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `sp_RefreshToken_Create`(
IN p_id_user INT,
IN p_token_hash VARCHAR(512),
IN p_token_salt VARCHAR(512),
IN p_expires_in_seconds INT,
IN p_device_info VARCHAR(255),
IN p_user_agent VARCHAR(512)
)
BEGIN
INSERT INTO refresh_token
(
id_user,
token_hash,
token_salt,
expires_at,
device_info,
user_agent
)
VALUES
(
p_id_user,
p_token_hash,
p_token_salt,
DATE_ADD(UTC_TIMESTAMP(), INTERVAL p_expires_in_seconds SECOND),
p_device_info,
p_user_agent
);
SELECT LAST_INSERT_ID() AS id_refresh_token;
utf8mb4_0900_ai_ci;;
DELIMITER ;
@@ -0,0 +1,21 @@
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `sp_RefreshToken_GetById`(IN p_id_refresh_token INT)
BEGIN
SELECT
id_refresh_token,
id_user,
token_hash,
token_salt,
expires_at,
last_used_at,
revoked_at,
device_info,
user_agent,
replaced_by_token_id,
created_at,
updated_at
FROM refresh_token
WHERE id_refresh_token = p_id_refresh_token
LIMIT 1;
utf8mb4_0900_ai_ci;;
DELIMITER ;
@@ -0,0 +1,43 @@
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `sp_RefreshToken_Replace`(
IN p_old_token_id INT,
IN p_id_user INT,
IN p_token_hash VARCHAR(512),
IN p_token_salt VARCHAR(512),
IN p_expires_in_seconds INT,
IN p_device_info VARCHAR(255),
IN p_user_agent VARCHAR(512)
)
BEGIN
-- Revoke the old token
UPDATE refresh_token
SET revoked_at = UTC_TIMESTAMP()
WHERE id_refresh_token = p_old_token_id
AND revoked_at IS NULL;
-- Create the new token
INSERT INTO refresh_token
(
id_user,
token_hash,
token_salt,
expires_at,
device_info,
user_agent
)
VALUES
(
p_id_user,
p_token_hash,
p_token_salt,
DATE_ADD(UTC_TIMESTAMP(), INTERVAL p_expires_in_seconds SECOND),
p_device_info,
p_user_agent
);
-- Link old token to new one
SET @new_id = LAST_INSERT_ID();
UPDATE refresh_token
SET replaced_by_token_id = @new_id
WHERE id_refresh_token = p_old_token_id;
SELECT @new_id AS id_refresh_token;
utf8mb4_0900_ai_ci;;
DELIMITER ;
@@ -0,0 +1,10 @@
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `sp_RefreshToken_Revoke`(IN p_id_refresh_token INT)
BEGIN
UPDATE refresh_token
SET revoked_at = UTC_TIMESTAMP()
WHERE id_refresh_token = p_id_refresh_token
AND revoked_at IS NULL;
SELECT ROW_COUNT() AS rows_affected;
utf8mb4_0900_ai_ci;;
DELIMITER ;
+3 -7
View File
@@ -1,12 +1,8 @@
DROP PROCEDURE IF EXISTS sp_Student_Delete;
DELIMITER $$
CREATE PROCEDURE sp_Student_Delete(IN p_id_student INT)
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `sp_Student_Delete`(IN p_id_student INT)
BEGIN
DELETE FROM student
WHERE id_student = p_id_student;
SELECT ROW_COUNT() AS rows_affected;
END$$
utf8mb4_0900_ai_ci;;
DELIMITER ;
+3 -6
View File
@@ -1,7 +1,5 @@
DROP PROCEDURE IF EXISTS sp_Student_GetAll;
DELIMITER $$
CREATE PROCEDURE sp_Student_GetAll()
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `sp_Student_GetAll`()
BEGIN
SELECT
id_student,
@@ -13,6 +11,5 @@ BEGIN
created_at
FROM student
ORDER BY id_student;
END$$
utf8mb4_0900_ai_ci;;
DELIMITER ;
+3 -6
View File
@@ -1,7 +1,5 @@
DROP PROCEDURE IF EXISTS sp_Student_GetById;
DELIMITER $$
CREATE PROCEDURE sp_Student_GetById(IN p_id_student INT)
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `sp_Student_GetById`(IN p_id_student INT)
BEGIN
SELECT
id_student,
@@ -14,6 +12,5 @@ BEGIN
FROM student
WHERE id_student = p_id_student
LIMIT 1;
END$$
utf8mb4_0900_ai_ci;;
DELIMITER ;
+3 -7
View File
@@ -1,7 +1,5 @@
DROP PROCEDURE IF EXISTS sp_Student_Insert;
DELIMITER $$
CREATE PROCEDURE sp_Student_Insert(
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `sp_Student_Insert`(
IN p_id_student INT,
IN p_id_program INT,
IN p_identifier VARCHAR(50),
@@ -30,7 +28,6 @@ BEGIN
p_expected_grad,
UTC_TIMESTAMP()
);
SELECT
id_student,
id_program,
@@ -42,6 +39,5 @@ BEGIN
FROM student
WHERE id_student = p_id_student
LIMIT 1;
END$$
utf8mb4_0900_ai_ci;;
DELIMITER ;
+3 -7
View File
@@ -1,7 +1,5 @@
DROP PROCEDURE IF EXISTS sp_Student_Update;
DELIMITER $$
CREATE PROCEDURE sp_Student_Update(
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `sp_Student_Update`(
IN p_id_student INT,
IN p_id_program INT,
IN p_identifier VARCHAR(50),
@@ -18,8 +16,6 @@ BEGIN
enrollment_date = COALESCE(p_enrollment_date, enrollment_date),
expected_grad = COALESCE(p_expected_grad, expected_grad)
WHERE id_student = p_id_student;
SELECT ROW_COUNT() AS rows_affected;
END$$
utf8mb4_0900_ai_ci;;
DELIMITER ;
@@ -0,0 +1,20 @@
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `sp_User_GetByEmail`(IN p_email VARCHAR(255))
BEGIN
SELECT
u.id_user,
u.id_role,
u.email,
u.name,
u.password_hash,
u.password_salt,
u.failed_login_attempts,
u.locked_until,
u.created_at,
r.name AS role_name
FROM `user` u
LEFT JOIN role r ON u.id_role = r.id_role
WHERE u.email = p_email
LIMIT 1;
utf8mb4_0900_ai_ci;;
DELIMITER ;
+20
View File
@@ -0,0 +1,20 @@
DELIMITER ;;
CREATE DEFINER=`root`@`%` PROCEDURE `sp_User_GetById`(IN p_id_user INT)
BEGIN
SELECT
u.id_user,
u.id_role,
u.email,
u.name,
u.password_hash,
u.password_salt,
u.failed_login_attempts,
u.locked_until,
u.created_at,
r.name AS role_name
FROM `user` u
LEFT JOIN role r ON u.id_role = r.id_role
WHERE u.id_user = p_id_user
LIMIT 1;
utf8mb4_0900_ai_ci;;
DELIMITER ;
+20
View File
@@ -0,0 +1,20 @@
CREATE TABLE `refresh_token` (
`id_refresh_token` int NOT NULL AUTO_INCREMENT,
`id_user` int NOT NULL,
`token_hash` varchar(512) NOT NULL,
`token_salt` varchar(512) NOT NULL,
`expires_at` timestamp NOT NULL,
`last_used_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`revoked_at` timestamp NULL DEFAULT NULL,
`device_info` varchar(255) DEFAULT NULL,
`user_agent` varchar(512) DEFAULT NULL,
`replaced_by_token_id` int DEFAULT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id_refresh_token`),
KEY `idx_refresh_token_user` (`id_user`),
KEY `idx_refresh_token_expires` (`expires_at`),
KEY `refresh_token_ibfk_2` (`replaced_by_token_id`),
CONSTRAINT `refresh_token_ibfk_1` FOREIGN KEY (`id_user`) REFERENCES `user` (`id_user`),
CONSTRAINT `refresh_token_ibfk_2` FOREIGN KEY (`replaced_by_token_id`) REFERENCES `refresh_token` (`id_refresh_token`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+1
View File
@@ -4,6 +4,7 @@ CREATE TABLE `user` (
`email` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
`password_hash` varchar(255) DEFAULT NULL,
`password_salt` varchar(255) DEFAULT NULL,
`password_updated_at` timestamp NULL DEFAULT NULL,
`failed_login_attempts` int DEFAULT '0',
`locked_until` timestamp NULL DEFAULT NULL,
+194
View File
@@ -0,0 +1,194 @@
#!/bin/bash
# dump-objects.sh
MYSQL="mysql"
BASE_OUTPUT_DIR="$(cd "$(dirname "$0")" && pwd)/Objects"
DATABASE="winstudentgoaltracker"
# Get password once
read -s -p "Enter MySQL password: " PASS
echo
# Connection parameters
CONN_PARAMS=(-h 10.66.66.1 -P 3309 -u root -p"$PASS")
# =============================================================================
# CONNECTION TEST
# =============================================================================
echo "Testing connection to MySQL..."
if ! $MYSQL "${CONN_PARAMS[@]}" -N -B --raw -e "SELECT 1" &>/dev/null; then
echo ""
echo "ERROR: Could not connect to MySQL."
echo "Check your password, host (10.66.66.1), port (3309), and that the MySQL server is reachable."
exit 1
fi
echo "Connection OK."
# Helper function to initialize output directory
initialize_output_dir() {
local path="$1"
if [ -d "$path" ]; then
rm -f "$path"/*.sql 2>/dev/null
else
mkdir -p "$path"
fi
echo "$path"
}
# Helper function to run mysql and clean output
invoke_mysql_query() {
local query="$1"
$MYSQL "${CONN_PARAMS[@]}" -N -B --raw -e "$query" 2>/dev/null | tr -d '\r' | sed '/^$/d'
}
# =============================================================================
# TABLES (includes indexes; triggers handled separately)
# =============================================================================
TABLE_DIR=$(initialize_output_dir "$BASE_OUTPUT_DIR/tables")
echo ""
echo "Fetching table list..."
TABLES=()
while IFS= read -r line; do
[ -n "$line" ] && TABLES+=("$line")
done < <(invoke_mysql_query "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA = '$DATABASE' AND TABLE_TYPE = 'BASE TABLE'")
echo "Found ${#TABLES[@]} tables"
for table in "${TABLES[@]}"; do
table=$(echo "$table" | xargs)
[ -z "$table" ] && continue
echo " Dumping: $table"
create_stmt=$(invoke_mysql_query "SHOW CREATE TABLE \`$DATABASE\`.\`$table\`" | cut -f2-)
if [ -z "$create_stmt" ]; then
echo "WARNING: Failed to dump table: $table" >&2
continue
fi
# Get triggers for this table
TRIGGERS=()
while IFS= read -r line; do
[ -n "$line" ] && TRIGGERS+=("$line")
done < <(invoke_mysql_query "SELECT TRIGGER_NAME FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA = '$DATABASE' AND EVENT_OBJECT_TABLE = '$table'")
trigger_sql=""
for trigger in "${TRIGGERS[@]}"; do
trigger=$(echo "$trigger" | xargs)
[ -z "$trigger" ] && continue
trigger_def=$(invoke_mysql_query "SHOW CREATE TRIGGER \`$DATABASE\`.\`$trigger\`")
if [ -n "$trigger_def" ]; then
# SHOW CREATE TRIGGER: TriggerName<TAB>sql_mode<TAB>CreateStatement<TAB>...
trigger_create=$(echo "$trigger_def" | cut -f3 | sed 's/\t.*$//')
trigger_sql+=$'\n\nDELIMITER ;;\n'"$trigger_create"$';;\nDELIMITER ;'
fi
done
printf '%s;%s\n' "$create_stmt" "$trigger_sql" > "$TABLE_DIR/$table.sql"
done
# =============================================================================
# VIEWS
# =============================================================================
VIEW_DIR=$(initialize_output_dir "$BASE_OUTPUT_DIR/views")
echo ""
echo "Fetching view list..."
VIEWS=()
while IFS= read -r line; do
[ -n "$line" ] && VIEWS+=("$line")
done < <(invoke_mysql_query "SELECT TABLE_NAME FROM information_schema.VIEWS WHERE TABLE_SCHEMA = '$DATABASE'")
echo "Found ${#VIEWS[@]} views"
for view in "${VIEWS[@]}"; do
view=$(echo "$view" | xargs)
[ -z "$view" ] && continue
echo " Dumping: $view"
create_stmt=$(invoke_mysql_query "SHOW CREATE VIEW \`$DATABASE\`.\`$view\`" | cut -f2 | sed 's/\t[^\t]*\t[^\t]*$//')
if [ -z "$create_stmt" ]; then
echo "WARNING: Failed to dump view: $view" >&2
continue
fi
# Basic formatting to break long lines
create_stmt=$(echo "$create_stmt" | sed \
-e 's/ select /\nselect /g' \
-e 's/ from /\nfrom /g' \
-e 's/ left join /\nleft join /g' \
-e 's/ inner join /\ninner join /g' \
-e 's/ join /\njoin /g' \
-e 's/ where /\nwhere /g' \
-e 's/ and /\n and /g' \
-e 's/ or /\n or /g')
printf '%s;\n' "$create_stmt" > "$VIEW_DIR/$view.sql"
done
# =============================================================================
# FUNCTIONS
# =============================================================================
FUNCTION_DIR=$(initialize_output_dir "$BASE_OUTPUT_DIR/functions")
echo ""
echo "Fetching function list..."
FUNCTIONS=()
while IFS= read -r line; do
[ -n "$line" ] && FUNCTIONS+=("$line")
done < <(invoke_mysql_query "SELECT ROUTINE_NAME FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = '$DATABASE' AND ROUTINE_TYPE = 'FUNCTION'")
echo "Found ${#FUNCTIONS[@]} functions"
for func in "${FUNCTIONS[@]}"; do
func=$(echo "$func" | xargs)
[ -z "$func" ] && continue
echo " Dumping: $func"
# SHOW CREATE FUNCTION: FuncName<TAB>sql_mode<TAB>CreateStatement<TAB>...
create_stmt=$(invoke_mysql_query "SHOW CREATE FUNCTION \`$DATABASE\`.\`$func\`" | cut -f3 | sed 's/END\t.*/END/')
if [ -z "$create_stmt" ]; then
echo "WARNING: Failed to dump function: $func" >&2
continue
fi
printf 'DELIMITER ;;\n%s;;\nDELIMITER ;\n' "$create_stmt" > "$FUNCTION_DIR/$func.sql"
done
# =============================================================================
# PROCEDURES
# =============================================================================
PROCEDURE_DIR=$(initialize_output_dir "$BASE_OUTPUT_DIR/procedures")
echo ""
echo "Fetching procedure list..."
PROCS=()
while IFS= read -r line; do
[ -n "$line" ] && PROCS+=("$line")
done < <(invoke_mysql_query "SELECT ROUTINE_NAME FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = '$DATABASE' AND ROUTINE_TYPE = 'PROCEDURE'")
echo "Found ${#PROCS[@]} procedures"
for proc in "${PROCS[@]}"; do
proc=$(echo "$proc" | xargs)
[ -z "$proc" ] && continue
echo " Dumping: $proc"
# SHOW CREATE PROCEDURE: ProcName<TAB>sql_mode<TAB>CreateStatement<TAB>...
create_stmt=$(invoke_mysql_query "SHOW CREATE PROCEDURE \`$DATABASE\`.\`$proc\`" | cut -f3 | sed 's/END\t.*/END/')
if [ -z "$create_stmt" ]; then
echo "WARNING: Failed to dump procedure: $proc" >&2
continue
fi
printf 'DELIMITER ;;\n%s;;\nDELIMITER ;\n' "$create_stmt" > "$PROCEDURE_DIR/$proc.sql"
done
# =============================================================================
# SUMMARY
# =============================================================================
echo ""
echo "=========================================="
echo "Done! Schema exported to: $BASE_OUTPUT_DIR"
echo " Tables: ${#TABLES[@]}"
echo " Views: ${#VIEWS[@]}"
echo " Functions: ${#FUNCTIONS[@]}"
echo " Procedures: ${#PROCS[@]}"
echo "=========================================="