mirror of
https://github.com/databasus/databasus.git
synced 2026-04-06 00:32:03 +02:00
merge develop
This commit is contained in:
@@ -6,14 +6,14 @@ repos:
|
||||
hooks:
|
||||
- id: frontend-format
|
||||
name: Frontend Format (Prettier)
|
||||
entry: powershell -Command "cd frontend; npm run format"
|
||||
entry: bash -c "cd frontend && npm run format"
|
||||
language: system
|
||||
files: ^frontend/.*\.(ts|tsx|js|jsx|json|css|md)$
|
||||
pass_filenames: false
|
||||
|
||||
- id: frontend-lint
|
||||
name: Frontend Lint (ESLint)
|
||||
entry: powershell -Command "cd frontend; npm run lint"
|
||||
entry: bash -c "cd frontend && npm run lint"
|
||||
language: system
|
||||
files: ^frontend/.*\.(ts|tsx|js|jsx)$
|
||||
pass_filenames: false
|
||||
@@ -23,7 +23,7 @@ repos:
|
||||
hooks:
|
||||
- id: backend-format-and-lint
|
||||
name: Backend Format & Lint (golangci-lint)
|
||||
entry: powershell -Command "cd backend; golangci-lint fmt; golangci-lint run"
|
||||
entry: bash -c "cd backend && golangci-lint run --fix"
|
||||
language: system
|
||||
files: ^backend/.*\.go$
|
||||
pass_filenames: false
|
||||
@@ -32,5 +32,5 @@ keywords:
|
||||
- mongodb
|
||||
- mariadb
|
||||
license: Apache-2.0
|
||||
version: 2.18.1
|
||||
date-released: "2025-12-28"
|
||||
version: 2.21.0
|
||||
date-released: "2026-01-05"
|
||||
|
||||
@@ -9,13 +9,13 @@ echo "Installing PostgreSQL, MySQL, MariaDB and MongoDB client tools for Linux (
|
||||
echo
|
||||
|
||||
# Check if running on supported system
|
||||
if ! command -v apt-get > /dev/null 2>&1; then
|
||||
if ! command -v apt-get &> /dev/null; then
|
||||
echo "Error: This script requires apt-get (Debian/Ubuntu-like system)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if running as root or with sudo
|
||||
if [ $EUID -eq 0 ]; then
|
||||
if [[ $EUID -eq 0 ]]; then
|
||||
SUDO=""
|
||||
else
|
||||
SUDO="sudo"
|
||||
@@ -107,12 +107,6 @@ for version in $mysql_versions; do
|
||||
version_dir="$MYSQL_DIR/mysql-$version"
|
||||
mkdir -p "$version_dir/bin"
|
||||
|
||||
# Skip if already exists
|
||||
if [ -f "$version_dir/bin/mysqldump" ]; then
|
||||
echo " MySQL $version already installed, skipping..."
|
||||
continue
|
||||
fi
|
||||
|
||||
# Download MySQL client tools from official CDN
|
||||
# Note: 5.7 is in Downloads, 8.0, 8.4 specific versions are in archives, 9.5 is in MySQL-9.5
|
||||
case $version in
|
||||
@@ -138,14 +132,11 @@ for version in $mysql_versions; do
|
||||
wget -q "$MYSQL_URL" -O "mysql-$version.tar.gz" || wget -q "$MYSQL_URL" -O "mysql-$version.tar.xz"
|
||||
|
||||
echo " Extracting MySQL $version..."
|
||||
case "$MYSQL_URL" in
|
||||
*.xz)
|
||||
tar -xJf "mysql-$version.tar.xz" 2>/dev/null || tar -xJf "mysql-$version.tar.gz" 2>/dev/null
|
||||
;;
|
||||
*)
|
||||
tar -xzf "mysql-$version.tar.gz" 2>/dev/null || tar -xzf "mysql-$version.tar.xz" 2>/dev/null
|
||||
;;
|
||||
esac
|
||||
if [[ "$MYSQL_URL" == *.xz ]]; then
|
||||
tar -xJf "mysql-$version.tar.xz" 2>/dev/null || tar -xJf "mysql-$version.tar.gz" 2>/dev/null
|
||||
else
|
||||
tar -xzf "mysql-$version.tar.gz" 2>/dev/null || tar -xzf "mysql-$version.tar.xz" 2>/dev/null
|
||||
fi
|
||||
|
||||
# Find extracted directory
|
||||
EXTRACTED_DIR=$(ls -d mysql-*/ 2>/dev/null | head -1)
|
||||
@@ -184,7 +175,12 @@ echo "Installing MariaDB client tools to: $MARIADB_DIR"
|
||||
# Install dependencies
|
||||
$SUDO apt-get install -y -qq apt-transport-https curl
|
||||
|
||||
# MariaDB versions to install
|
||||
# MariaDB versions to install with their URLs
|
||||
declare -A MARIADB_URLS=(
|
||||
["10.6"]="https://archive.mariadb.org/mariadb-10.6.21/bintar-linux-systemd-x86_64/mariadb-10.6.21-linux-systemd-x86_64.tar.gz"
|
||||
["12.1"]="https://archive.mariadb.org/mariadb-12.1.2/bintar-linux-systemd-x86_64/mariadb-12.1.2-linux-systemd-x86_64.tar.gz"
|
||||
)
|
||||
|
||||
mariadb_versions="10.6 12.1"
|
||||
|
||||
for version in $mariadb_versions; do
|
||||
@@ -199,19 +195,7 @@ for version in $mariadb_versions; do
|
||||
continue
|
||||
fi
|
||||
|
||||
# Get URL based on version
|
||||
case "$version" in
|
||||
"10.6")
|
||||
url="https://archive.mariadb.org/mariadb-10.6.21/bintar-linux-systemd-x86_64/mariadb-10.6.21-linux-systemd-x86_64.tar.gz"
|
||||
;;
|
||||
"12.1")
|
||||
url="https://archive.mariadb.org/mariadb-12.1.2/bintar-linux-systemd-x86_64/mariadb-12.1.2-linux-systemd-x86_64.tar.gz"
|
||||
;;
|
||||
*)
|
||||
echo " Warning: Unknown MariaDB version $version"
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
url=${MARIADB_URLS[$version]}
|
||||
|
||||
TEMP_DIR="/tmp/mariadb_install_$version"
|
||||
mkdir -p "$TEMP_DIR"
|
||||
@@ -254,48 +238,43 @@ mkdir -p "$MONGODB_DIR/bin"
|
||||
|
||||
echo "Installing MongoDB Database Tools to: $MONGODB_DIR"
|
||||
|
||||
# Skip if already installed
|
||||
if [ -f "$MONGODB_DIR/bin/mongodump" ] && [ -L "$MONGODB_DIR/bin/mongodump" ]; then
|
||||
echo "MongoDB Database Tools already installed, skipping..."
|
||||
# MongoDB Database Tools are backward compatible - single version supports all servers (4.0-8.0)
|
||||
# Detect architecture
|
||||
ARCH=$(uname -m)
|
||||
if [ "$ARCH" = "x86_64" ]; then
|
||||
MONGODB_TOOLS_URL="https://fastdl.mongodb.org/tools/db/mongodb-database-tools-debian12-x86_64-100.10.0.deb"
|
||||
elif [ "$ARCH" = "aarch64" ]; then
|
||||
MONGODB_TOOLS_URL="https://fastdl.mongodb.org/tools/db/mongodb-database-tools-debian12-aarch64-100.10.0.deb"
|
||||
else
|
||||
# MongoDB Database Tools are backward compatible - single version supports all servers (4.0-8.0)
|
||||
# Detect architecture
|
||||
ARCH=$(uname -m)
|
||||
if [ "$ARCH" = "x86_64" ]; then
|
||||
MONGODB_TOOLS_URL="https://fastdl.mongodb.org/tools/db/mongodb-database-tools-debian12-x86_64-100.10.0.deb"
|
||||
elif [ "$ARCH" = "aarch64" ]; then
|
||||
MONGODB_TOOLS_URL="https://fastdl.mongodb.org/tools/db/mongodb-database-tools-debian12-aarch64-100.10.0.deb"
|
||||
else
|
||||
echo "Warning: Unsupported architecture $ARCH for MongoDB Database Tools"
|
||||
MONGODB_TOOLS_URL=""
|
||||
echo "Warning: Unsupported architecture $ARCH for MongoDB Database Tools"
|
||||
MONGODB_TOOLS_URL=""
|
||||
fi
|
||||
|
||||
if [ -n "$MONGODB_TOOLS_URL" ]; then
|
||||
TEMP_DIR="/tmp/mongodb_install"
|
||||
mkdir -p "$TEMP_DIR"
|
||||
cd "$TEMP_DIR"
|
||||
|
||||
echo "Downloading MongoDB Database Tools..."
|
||||
wget -q "$MONGODB_TOOLS_URL" -O mongodb-database-tools.deb || {
|
||||
echo "Warning: Could not download MongoDB Database Tools"
|
||||
cd - >/dev/null
|
||||
rm -rf "$TEMP_DIR"
|
||||
}
|
||||
|
||||
if [ -f "mongodb-database-tools.deb" ]; then
|
||||
echo "Installing MongoDB Database Tools..."
|
||||
$SUDO dpkg -i mongodb-database-tools.deb 2>/dev/null || $SUDO apt-get install -f -y -qq
|
||||
|
||||
# Create symlinks to tools directory
|
||||
ln -sf /usr/bin/mongodump "$MONGODB_DIR/bin/mongodump"
|
||||
ln -sf /usr/bin/mongorestore "$MONGODB_DIR/bin/mongorestore"
|
||||
|
||||
echo "MongoDB Database Tools installed successfully"
|
||||
fi
|
||||
|
||||
if [ -n "$MONGODB_TOOLS_URL" ]; then
|
||||
TEMP_DIR="/tmp/mongodb_install"
|
||||
mkdir -p "$TEMP_DIR"
|
||||
cd "$TEMP_DIR"
|
||||
|
||||
echo "Downloading MongoDB Database Tools..."
|
||||
if ! wget -q "$MONGODB_TOOLS_URL" -O mongodb-database-tools.deb; then
|
||||
echo "Warning: Could not download MongoDB Database Tools"
|
||||
cd - >/dev/null
|
||||
rm -rf "$TEMP_DIR"
|
||||
else
|
||||
if [ -f "mongodb-database-tools.deb" ]; then
|
||||
echo "Installing MongoDB Database Tools..."
|
||||
$SUDO dpkg -i mongodb-database-tools.deb 2>/dev/null || $SUDO apt-get install -f -y -qq
|
||||
|
||||
# Create symlinks to tools directory
|
||||
ln -sf /usr/bin/mongodump "$MONGODB_DIR/bin/mongodump"
|
||||
ln -sf /usr/bin/mongorestore "$MONGODB_DIR/bin/mongorestore"
|
||||
|
||||
echo "MongoDB Database Tools installed successfully"
|
||||
fi
|
||||
|
||||
cd - >/dev/null
|
||||
rm -rf "$TEMP_DIR"
|
||||
fi
|
||||
fi
|
||||
cd - >/dev/null
|
||||
rm -rf "$TEMP_DIR"
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
@@ -2,4 +2,5 @@ export interface GoogleDriveStorage {
|
||||
clientId: string;
|
||||
clientSecret: string;
|
||||
tokenJson?: string;
|
||||
useLocalRedirect?: boolean;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button, Input } from 'antd';
|
||||
import { Button, Checkbox, Input } from 'antd';
|
||||
|
||||
import { GOOGLE_DRIVE_OAUTH_REDIRECT_URL } from '../../../../../constants';
|
||||
import type { Storage } from '../../../../../entity/storages';
|
||||
@@ -16,7 +16,10 @@ export function EditGoogleDriveStorageComponent({ storage, setStorage, setUnsave
|
||||
return;
|
||||
}
|
||||
|
||||
const redirectUri = GOOGLE_DRIVE_OAUTH_REDIRECT_URL;
|
||||
const localRedirectUri = `${window.location.origin}/storages/google-oauth`;
|
||||
const useLocal = storage.googleDriveStorage.useLocalRedirect;
|
||||
const redirectUri = useLocal ? localRedirectUri : GOOGLE_DRIVE_OAUTH_REDIRECT_URL;
|
||||
|
||||
const clientId = storage.googleDriveStorage.clientId;
|
||||
const scope = 'https://www.googleapis.com/auth/drive.file';
|
||||
const originUrl = `${window.location.origin}/storages/google-oauth`;
|
||||
@@ -92,6 +95,28 @@ export function EditGoogleDriveStorageComponent({ storage, setStorage, setUnsave
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-4 flex w-full flex-col items-start sm:flex-row sm:items-center">
|
||||
<div className="mb-1 min-w-[110px] sm:mb-0" />
|
||||
<Checkbox
|
||||
checked={storage?.googleDriveStorage?.useLocalRedirect || false}
|
||||
onChange={(e) => {
|
||||
if (!storage?.googleDriveStorage) return;
|
||||
|
||||
setStorage({
|
||||
...storage,
|
||||
googleDriveStorage: {
|
||||
...storage.googleDriveStorage,
|
||||
useLocalRedirect: e.target.checked,
|
||||
},
|
||||
});
|
||||
setUnsaved();
|
||||
}}
|
||||
disabled={!!storage?.googleDriveStorage?.tokenJson}
|
||||
>
|
||||
<span className="text-xs">Use local redirect (more secure)</span>
|
||||
</Checkbox>
|
||||
</div>
|
||||
|
||||
{storage?.googleDriveStorage?.tokenJson && (
|
||||
<>
|
||||
<div className="mb-1 flex w-full flex-col items-start sm:flex-row sm:items-center">
|
||||
|
||||
@@ -19,6 +19,11 @@ export function ShowGoogleDriveStorageComponent({ storage }: Props) {
|
||||
{`*************`}
|
||||
</div>
|
||||
|
||||
<div className="mb-1 flex items-center">
|
||||
<div className="min-w-[110px]">Use local redirect</div>
|
||||
{`*************`}
|
||||
</div>
|
||||
|
||||
<div className="mb-1 flex items-center">
|
||||
<div className="min-w-[110px]">User Token</div>
|
||||
{`*************`}
|
||||
|
||||
@@ -18,6 +18,8 @@ export function OauthStorageComponent() {
|
||||
const { clientId, clientSecret } = oauthDto.storage.googleDriveStorage;
|
||||
const { authCode } = oauthDto;
|
||||
|
||||
const redirectUri = oauthDto.redirectUrl || GOOGLE_DRIVE_OAUTH_REDIRECT_URL;
|
||||
|
||||
try {
|
||||
// Exchange authorization code for access token
|
||||
const response = await fetch('https://oauth2.googleapis.com/token', {
|
||||
@@ -29,13 +31,16 @@ export function OauthStorageComponent() {
|
||||
code: authCode,
|
||||
client_id: clientId,
|
||||
client_secret: clientSecret,
|
||||
redirect_uri: GOOGLE_DRIVE_OAUTH_REDIRECT_URL,
|
||||
redirect_uri: redirectUri,
|
||||
grant_type: 'authorization_code',
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`OAuth exchange failed: ${response.statusText}`);
|
||||
const errorData = await response.json();
|
||||
throw new Error(
|
||||
errorData.error_description || `OAuth exchange failed: ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
|
||||
const tokenData = await response.json();
|
||||
@@ -44,27 +49,71 @@ export function OauthStorageComponent() {
|
||||
setStorage(oauthDto.storage);
|
||||
} catch (error) {
|
||||
alert(`Failed to exchange OAuth code: ${error}`);
|
||||
// Return to home if exchange fails
|
||||
setTimeout(() => {
|
||||
window.location.href = '/';
|
||||
}, 3000);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const oauthDtoParam = new URLSearchParams(window.location.search).get('oauthDto');
|
||||
if (!oauthDtoParam) {
|
||||
alert('OAuth param not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const decodedParam = decodeURIComponent(oauthDtoParam);
|
||||
const oauthDto: StorageOauthDto = JSON.parse(decodedParam);
|
||||
|
||||
/**
|
||||
* Helper to validate the DTO and start the exchange process
|
||||
*/
|
||||
const processOauthDto = (oauthDto: StorageOauthDto) => {
|
||||
if (oauthDto.storage.type === StorageType.GOOGLE_DRIVE) {
|
||||
if (!oauthDto.storage.googleDriveStorage) {
|
||||
alert('Google Drive storage not found');
|
||||
alert('Google Drive storage configuration not found in DTO');
|
||||
return;
|
||||
}
|
||||
|
||||
exchangeGoogleOauthCode(oauthDto);
|
||||
} else {
|
||||
alert('Unsupported storage type for OAuth');
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
|
||||
// Attempt 1: Check for the 'oauthDto' param (Third-party/Legacy way)
|
||||
const oauthDtoParam = urlParams.get('oauthDto');
|
||||
if (oauthDtoParam) {
|
||||
try {
|
||||
const decodedParam = decodeURIComponent(oauthDtoParam);
|
||||
const oauthDto: StorageOauthDto = JSON.parse(decodedParam);
|
||||
processOauthDto(oauthDto);
|
||||
return;
|
||||
} catch (e) {
|
||||
console.error('Error parsing oauthDto parameter:', e);
|
||||
alert('Malformed OAuth parameter received');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt 2: Check for 'code' and 'state' (Direct Google/Local way)
|
||||
const code = urlParams.get('code');
|
||||
const state = urlParams.get('state');
|
||||
|
||||
if (code && state) {
|
||||
try {
|
||||
// The 'state' parameter contains our stringified StorageOauthDto
|
||||
const decodedState = decodeURIComponent(state);
|
||||
const oauthDto: StorageOauthDto = JSON.parse(decodedState);
|
||||
|
||||
// Inject the authorization code received from Google
|
||||
oauthDto.authCode = code;
|
||||
|
||||
processOauthDto(oauthDto);
|
||||
return;
|
||||
} catch (e) {
|
||||
console.error('Error parsing OAuth state:', e);
|
||||
alert('OAuth state parameter is invalid');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt 3: No valid parameters found
|
||||
alert('OAuth param not found. Ensure the redirect URL is configured correctly.');
|
||||
}, []);
|
||||
|
||||
if (!storage) {
|
||||
|
||||
Reference in New Issue
Block a user