merge develop

This commit is contained in:
Rostislav Dugin
2026-01-08 11:33:34 +03:00
parent 02e86ffb3b
commit dbfeb9e27f
7 changed files with 149 additions and 90 deletions

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -2,4 +2,5 @@ export interface GoogleDriveStorage {
clientId: string;
clientSecret: string;
tokenJson?: string;
useLocalRedirect?: boolean;
}

View File

@@ -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">

View File

@@ -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>
{`*************`}

View File

@@ -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) {