From fac4edce1ec2acc0698381ae963764c72acc94ff Mon Sep 17 00:00:00 2001 From: melton-jason Date: Thu, 30 Jul 2026 21:58:50 -0500 Subject: [PATCH 1/3] fix: inherit host for authenticated connection and allow host configuration --- sp7_db_setup_check.sh | 45 ++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/sp7_db_setup_check.sh b/sp7_db_setup_check.sh index 0cb250b7145..a70f2cff864 100644 --- a/sp7_db_setup_check.sh +++ b/sp7_db_setup_check.sh @@ -169,13 +169,14 @@ fi # Detect client host as seen by MariaDB CLIENT_HOST="$(mariadb -N -B -h "$DB_HOST" -P "$DB_PORT" \ -u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" \ - -sse "SELECT SUBSTRING_INDEX(USER(),'@',-1);")" || CLIENT_HOST="" + -sse "SELECT SUBSTRING_INDEX(CURRENT_USER(),'@',-1);")" || CLIENT_HOST="" CLIENT_HOST="${CLIENT_HOST%% *}" +MIGRATOR_USER_HOST="${MIGRATOR_USER_HOST:-${CLIENT_HOST:-}}" +APP_USER_HOST="${APP_USER_HOST:-${CLIENT_HOST:-}}" + if [[ -n "$CLIENT_HOST" ]]; then echo "Client host as seen by MariaDB: '$CLIENT_HOST'" -else - echo "Warning: Could not detect client host via USER(); will only create users for explicit *_HOST values." fi # Create database if it doesn't exist @@ -203,13 +204,13 @@ if [[ "$SAME_MASTER_AND_MIGRATOR" == true ]]; then echo "Relying on master privileges for runtime connections." else USER_EXISTS=$(mysql -h "$DB_HOST" -P "$DB_PORT" -u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" -sse \ -"SELECT COUNT(*) FROM mysql.user WHERE user = '$SQL_MIGRATOR_NAME' AND host = '$CLIENT_HOST';") +"SELECT COUNT(*) FROM mysql.user WHERE user = '$SQL_MIGRATOR_NAME' AND host = '$MIGRATOR_USER_HOST';") if [[ "$USER_EXISTS" -eq 0 && "$MIGRATOR_NAME" != "root" ]]; then echo "Creating migrator user '$MIGRATOR_NAME'..." - echo "Executing: mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$MASTER_USER_NAME\" --password=\"\" -e \"CREATE USER '${SQL_MIGRATOR_NAME}'@'${CLIENT_HOST}' IDENTIFIED BY '';\"" + echo "Executing: mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$MASTER_USER_NAME\" --password=\"\" -e \"CREATE USER '${SQL_MIGRATOR_NAME}'@'${MIGRATOR_USER_HOST}' IDENTIFIED BY '';\"" if mysql -h "$DB_HOST" -P "$DB_PORT" -u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" \ - -e "CREATE USER '$SQL_MIGRATOR_NAME'@'$CLIENT_HOST' IDENTIFIED BY '$SQL_MIGRATOR_PASSWORD';"; then + -e "CREATE USER '$SQL_MIGRATOR_NAME'@'$MIGRATOR_USER_HOST' IDENTIFIED BY '$SQL_MIGRATOR_PASSWORD';"; then NEW_MIGRATOR_USER_CREATED=1 else echo "Error: Failed to create user." @@ -225,20 +226,20 @@ else echo "Migrator user already exists. Refreshing privileges on '${DB_NAME}'..." fi -echo "Executing: mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$MASTER_USER_NAME\" --password=\"\" -e \"GRANT ALL PRIVILEGES ON \`${SQL_DB_IDENTIFIER}\`.* TO '${SQL_MIGRATOR_NAME}'@'${CLIENT_HOST}'; FLUSH PRIVILEGES;\"" +echo "Executing: mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$MASTER_USER_NAME\" --password=\"\" -e \"GRANT ALL PRIVILEGES ON \`${SQL_DB_IDENTIFIER}\`.* TO '${SQL_MIGRATOR_NAME}'@'${MIGRATOR_USER_HOST}'; FLUSH PRIVILEGES;\"" if ! mysql -h "$DB_HOST" -P "$DB_PORT" -u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" \ - -e "GRANT ALL PRIVILEGES ON \`${SQL_DB_IDENTIFIER}\`.* TO '${SQL_MIGRATOR_NAME}'@'${CLIENT_HOST}'; FLUSH PRIVILEGES;"; then + -e "GRANT ALL PRIVILEGES ON \`${SQL_DB_IDENTIFIER}\`.* TO '${SQL_MIGRATOR_NAME}'@'${MIGRATOR_USER_HOST}'; FLUSH PRIVILEGES;"; then echo "Error: Failed to grant privileges to migrator user." exit 1 fi GRANTS_OUTPUT="$(mysql -N -B --raw -h "$DB_HOST" -P "$DB_PORT" \ -u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" \ - -e "SHOW GRANTS FOR '${SQL_MIGRATOR_NAME}'@'${CLIENT_HOST}';" 2>/dev/null || true)" + -e "SHOW GRANTS FOR '${SQL_MIGRATOR_NAME}'@'${MIGRATOR_USER_HOST}';" 2>/dev/null || true)" if [[ -z "$GRANTS_OUTPUT" ]]; then - echo "Error: Could not retrieve grants for '${SQL_MIGRATOR_NAME}'@'${CLIENT_HOST}'." + echo "Error: Could not retrieve grants for '${SQL_MIGRATOR_NAME}'@'${MIGRATOR_USER_HOST}'." exit 1 fi @@ -253,9 +254,9 @@ for g in "${MIGRATOR_GRANTS_LINES[@]}"; do done if [[ "$migrator_has_required_permissions" == true ]]; then - echo "Verified: '${SQL_MIGRATOR_NAME}'@'${CLIENT_HOST}' has migration privileges on '${DB_NAME}'." + echo "Verified: '${SQL_MIGRATOR_NAME}'@'${MIGRATOR_USER_HOST}' has migration privileges on '${DB_NAME}'." else - echo "Error: '${SQL_MIGRATOR_NAME}'@'${CLIENT_HOST}' lacks migration privileges on '${DB_NAME}'." + echo "Error: '${SQL_MIGRATOR_NAME}'@'${MIGRATOR_USER_HOST}' lacks migration privileges on '${DB_NAME}'." echo "Required for migrations (any one GRANT must include all of): ${MIGRATION_REQUIRED_PRIVS[*]}" echo "Grants found:" echo "$GRANTS_OUTPUT" @@ -265,16 +266,16 @@ fi # Create app user if it doesn't exist USER_EXISTS=$(mysql -h "$DB_HOST" -P "$DB_PORT" -u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" -sse \ -"SELECT COUNT(*) FROM mysql.user WHERE user = '$SQL_APP_USER_NAME' AND host = '$CLIENT_HOST';") +"SELECT COUNT(*) FROM mysql.user WHERE user = '$SQL_APP_USER_NAME' AND host = '$APP_USER_HOST';") if [[ "$USER_EXISTS" -eq 0 && "$APP_USER_NAME" != "root" ]]; then echo "Creating app user '$SQL_APP_USER_NAME'..." - echo "Executing: mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$MASTER_USER_NAME\" --password=\"\" -e \"CREATE USER '${SQL_APP_USER_NAME}'@'${CLIENT_HOST}' IDENTIFIED BY '';\"" + echo "Executing: mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$MASTER_USER_NAME\" --password=\"\" -e \"CREATE USER '${SQL_APP_USER_NAME}'@'${APP_USER_HOST}' IDENTIFIED BY '';\"" if mysql -h "$DB_HOST" -P "$DB_PORT" -u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" \ - -e "CREATE USER '$SQL_APP_USER_NAME'@'$CLIENT_HOST' IDENTIFIED BY '$SQL_APP_USER_PASSWORD';"; then + -e "CREATE USER '$SQL_APP_USER_NAME'@'$APP_USER_HOST' IDENTIFIED BY '$SQL_APP_USER_PASSWORD';"; then NEW_APP_USER_CREATED=1 else - echo "Error: Failed to create app user '${APP_USER_NAME}'@'${CLIENT_HOST}'." + echo "Error: Failed to create app user '${APP_USER_NAME}'@'${APP_USER_HOST}'." echo "Falling back to migrator credentials for app user." APP_USER_NAME="$MIGRATOR_NAME" APP_USER_PASSWORD="$MIGRATOR_PASSWORD" @@ -304,17 +305,17 @@ else echo "App user already exists. Refreshing privileges on '${DB_NAME}'..." fi -echo "Executing: mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$MASTER_USER_NAME\" --password=\"\" -e \"GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE ON \`${SQL_DB_IDENTIFIER}\`.* TO ${SQL_APP_USER_NAME}@'${CLIENT_HOST}'; FLUSH PRIVILEGES;\"" -if ! mysql -h "$DB_HOST" -P "$DB_PORT" -u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" -e "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE ON \`${SQL_DB_IDENTIFIER}\`.* TO '${SQL_APP_USER_NAME}'@'${CLIENT_HOST}'; FLUSH PRIVILEGES;"; then +echo "Executing: mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$MASTER_USER_NAME\" --password=\"\" -e \"GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE ON \`${SQL_DB_IDENTIFIER}\`.* TO ${SQL_APP_USER_NAME}@'${APP_USER_HOST}'; FLUSH PRIVILEGES;\"" +if ! mysql -h "$DB_HOST" -P "$DB_PORT" -u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" -e "GRANT SELECT, INSERT, UPDATE, DELETE, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE ON \`${SQL_DB_IDENTIFIER}\`.* TO '${SQL_APP_USER_NAME}'@'${APP_USER_HOST}'; FLUSH PRIVILEGES;"; then echo "Error: Failed to grant privileges to app user." exit 1 fi APP_GRANTS_RAW="$(mysql -N -B -h "$DB_HOST" -P "$DB_PORT" -u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" \ - -e "SHOW GRANTS FOR '${SQL_APP_USER_NAME}'@'${CLIENT_HOST}';" 2>/dev/null || true)" + -e "SHOW GRANTS FOR '${SQL_APP_USER_NAME}'@'${APP_USER_HOST}';" 2>/dev/null || true)" if [[ -z "$APP_GRANTS_RAW" ]]; then - echo "Error: Could not retrieve grants for '${SQL_APP_USER_NAME}'@'${CLIENT_HOST}'." + echo "Error: Could not retrieve grants for '${SQL_APP_USER_NAME}'@'${APP_USER_HOST}'." exit 1 fi @@ -330,9 +331,9 @@ for g in "${APP_GRANTS_LINES[@]}"; do done if [[ "$app_has_required_permissions" == true ]]; then - echo "Verified: '${APP_USER_NAME}'@'${CLIENT_HOST}' has required privileges on '${DB_NAME}'." + echo "Verified: '${APP_USER_NAME}'@'${APP_USER_HOST}' has required privileges on '${DB_NAME}'." else - echo "Error: '${APP_USER_NAME}'@'${CLIENT_HOST}' lacks required privileges on '${DB_NAME}'." + echo "Error: '${APP_USER_NAME}'@'${APP_USER_HOST}' lacks required privileges on '${DB_NAME}'." echo "Required (any one GRANT must include all of): ${APP_REQUIRED_PRIVS[*]}" echo "Grants found:" echo "$APP_GRANTS_RAW" From 9ebe0c9c996c12683ea77f3a5fdb10008ef071b6 Mon Sep 17 00:00:00 2001 From: melton-jason Date: Thu, 30 Jul 2026 22:29:12 -0500 Subject: [PATCH 2/3] feat: ignore explicit host variables when user name is the same --- sp7_db_setup_check.sh | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/sp7_db_setup_check.sh b/sp7_db_setup_check.sh index a70f2cff864..8d73a7fddd1 100644 --- a/sp7_db_setup_check.sh +++ b/sp7_db_setup_check.sh @@ -172,11 +172,18 @@ CLIENT_HOST="$(mariadb -N -B -h "$DB_HOST" -P "$DB_PORT" \ -sse "SELECT SUBSTRING_INDEX(CURRENT_USER(),'@',-1);")" || CLIENT_HOST="" CLIENT_HOST="${CLIENT_HOST%% *}" -MIGRATOR_USER_HOST="${MIGRATOR_USER_HOST:-${CLIENT_HOST:-}}" -APP_USER_HOST="${APP_USER_HOST:-${CLIENT_HOST:-}}" +if [[ "$SAME_MASTER_AND_MIGRATOR" == true ]]; then + MIGRATOR_USER_HOST="${CLIENT_HOST:-}" +else + MIGRATOR_USER_HOST="${MIGRATOR_USER_HOST:-${CLIENT_HOST:-}}" +fi -if [[ -n "$CLIENT_HOST" ]]; then - echo "Client host as seen by MariaDB: '$CLIENT_HOST'" +if [[ "$SAME_MASTER_AND_APP" == true ]]; then + APP_USER_HOST="${CLIENT_HOST:-}" +elif [[ "$SAME_MIGRATOR_AND_APP" == true ]]; then + APP_USER_HOST="${MIGRATOR_USER_HOST:-}" +else + APP_USER_HOST="${APP_USER_HOST:-${CLIENT_HOST:-}}" fi # Create database if it doesn't exist @@ -264,6 +271,8 @@ else fi fi +# BUG: this should probably be skipped if the app user is the same as the +# master or migrator # Create app user if it doesn't exist USER_EXISTS=$(mysql -h "$DB_HOST" -P "$DB_PORT" -u "$MASTER_USER_NAME" --password="$MASTER_USER_PASSWORD" -sse \ "SELECT COUNT(*) FROM mysql.user WHERE user = '$SQL_APP_USER_NAME' AND host = '$APP_USER_HOST';") From ef57132a60c00208667435d2e908883299eef4cd Mon Sep 17 00:00:00 2001 From: Grant Fitzsimmons <37256050+grantfitzsimmons@users.noreply.github.com> Date: Sun, 2 Aug 2026 02:08:04 +0000 Subject: [PATCH 3/3] Lint code with ESLint and Prettier Triggered by edd7b09c2e3a13ae429eb49da7b6d88704b1f482 on branch refs/heads/setup_script_hotfix --- .../AttachmentsBulkImport/Import.tsx | 12 ++-- .../MatchingModeDialog.tsx | 17 ++---- .../ViewAttachmentFiles.tsx | 7 ++- .../__tests__/utils.test.ts | 55 ++++++++++++------- .../AttachmentsBulkImport/useEagerDataset.ts | 3 +- .../components/AttachmentsBulkImport/utils.ts | 2 +- 6 files changed, 53 insertions(+), 43 deletions(-) diff --git a/specifyweb/frontend/js_src/lib/components/AttachmentsBulkImport/Import.tsx b/specifyweb/frontend/js_src/lib/components/AttachmentsBulkImport/Import.tsx index 0dcb673930c..6d90361c11d 100644 --- a/specifyweb/frontend/js_src/lib/components/AttachmentsBulkImport/Import.tsx +++ b/specifyweb/frontend/js_src/lib/components/AttachmentsBulkImport/Import.tsx @@ -199,9 +199,7 @@ function AttachmentsImport({ attachmentDataSetResource.uploadplan.staticPathKey ); React.useEffect(() => { - if ( - previousPathKeyRef.current !== eagerDataSet.uploadplan.staticPathKey - ) { + if (previousPathKeyRef.current !== eagerDataSet.uploadplan.staticPathKey) { previousPathKeyRef.current = eagerDataSet.uploadplan.staticPathKey; commitFileChange((files) => files.map(({ uploadFile, ...rest }) => ({ @@ -353,7 +351,10 @@ function AttachmentsImport({ if (process.env.NODE_ENV === 'development') headers = { ...headers, attachmentId: attachmentsText.attachmentId() }; return headers; - }, [eagerDataSet.uploadplan.staticPathKey, eagerDataSet.uploadplan.matchingMode]); + }, [ + eagerDataSet.uploadplan.staticPathKey, + eagerDataSet.uploadplan.matchingMode, + ]); const errorContextData = React.useMemo( () => ({ @@ -410,8 +411,7 @@ function AttachmentsImport({ matchingMode: oldState.uploadplan.matchingMode, mappingFileColumns: oldState.uploadplan.mappingFileColumns, - mappingFileData: - oldState.uploadplan.mappingFileData, + mappingFileData: oldState.uploadplan.mappingFileData, }, })); } diff --git a/specifyweb/frontend/js_src/lib/components/AttachmentsBulkImport/MatchingModeDialog.tsx b/specifyweb/frontend/js_src/lib/components/AttachmentsBulkImport/MatchingModeDialog.tsx index 952bce84dc1..8832046b383 100644 --- a/specifyweb/frontend/js_src/lib/components/AttachmentsBulkImport/MatchingModeDialog.tsx +++ b/specifyweb/frontend/js_src/lib/components/AttachmentsBulkImport/MatchingModeDialog.tsx @@ -8,11 +8,7 @@ import { Button } from '../Atoms/Button'; import { Submit } from '../Atoms/Submit'; import { Dialog } from '../Molecules/Dialog'; import { MappingFileSetup } from './MappingFileSetup'; -import type { - MappingFileColumns, - MappingFileRow, - MatchingMode, -} from './types'; +import type { MappingFileColumns, MappingFileRow, MatchingMode } from './types'; export function MatchingModeDialog({ onContinue: handleContinue, @@ -42,7 +38,8 @@ export function MatchingModeDialog({ >(initialData); const canContinue = - (mode === null || mode === undefined) || + mode === null || + mode === undefined || (mode === 'mappingFile' && mappingColumns !== undefined && mappingData !== undefined && @@ -56,9 +53,7 @@ export function MatchingModeDialog({ {commonText.close()} - handleContinue(mode, mappingColumns, mappingData) - } + onClick={() => handleContinue(mode, mappingColumns, mappingData)} > {commonText.proceed()} @@ -72,9 +67,7 @@ export function MatchingModeDialog({