mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-16 14:50:15 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e54e8ddb66 | ||
|
|
6560fff886 | ||
|
|
b01b939cf7 | ||
|
|
2c627132c0 | ||
|
|
1e77a8fc86 | ||
|
|
e38a7a94e2 |
+9
-3
@@ -22,9 +22,7 @@ import org.jkiss.dbeaver.model.DBPDataSource;
|
||||
import org.jkiss.dbeaver.model.DBUtils;
|
||||
import org.jkiss.dbeaver.model.data.DBDAttributeBinding;
|
||||
import org.jkiss.dbeaver.model.data.DBDRowIdentifier;
|
||||
import org.jkiss.dbeaver.model.struct.DBSAttributeBase;
|
||||
import org.jkiss.dbeaver.model.struct.DBSDataContainer;
|
||||
import org.jkiss.dbeaver.model.struct.DBSTypedObject;
|
||||
import org.jkiss.dbeaver.model.struct.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -126,4 +124,12 @@ public class WebSQLResultsInfo {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean canRefreshResults() {
|
||||
DBSEntity entity = getDefaultRowIdentifier().getEntity();
|
||||
// FIXME: do not refresh documents for now. Can be solved by extracting document ID attributes
|
||||
// FIXME: but it will require to provide dynamic document metadata.
|
||||
return entity == null || entity.getDataSource() == null ||
|
||||
(!(entity instanceof DBSDocumentContainer) && !entity.getDataSource().getInfo().isDynamicMetadata());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -557,7 +557,12 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
} else if (serverURL == null) {
|
||||
String hostName = serverHost;
|
||||
if (CommonUtils.isEmpty(hostName)) {
|
||||
hostName = InetAddress.getLocalHost().getHostName();
|
||||
try {
|
||||
hostName = InetAddress.getLocalHost().getHostName();
|
||||
} catch (UnknownHostException e) {
|
||||
log.debug("Error resolving localhost address: " + e.getMessage());
|
||||
hostName = "localhost";
|
||||
}
|
||||
}
|
||||
serverURL = "http://" + hostName + ":" + serverPort;
|
||||
}
|
||||
@@ -604,7 +609,7 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
}
|
||||
}
|
||||
parseAdditionalConfiguration(configProps);
|
||||
} catch (IOException | DBException e) {
|
||||
} catch (DBException e) {
|
||||
throw new DBException("Error parsing server configuration", e);
|
||||
}
|
||||
|
||||
|
||||
+26
-1
@@ -58,6 +58,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Web SQL processor.
|
||||
@@ -417,13 +418,22 @@ public class WebSQLProcessor implements WebSessionProvider {
|
||||
DBCExecutionPurpose.UTIL,
|
||||
"Refresh row(s) after insert/update")
|
||||
) {
|
||||
boolean canRefreshResults = resultsInfo.canRefreshResults();
|
||||
for (Object[] row : newResultSetRows) {
|
||||
if (row.length == 0) {
|
||||
continue;
|
||||
}
|
||||
if (!canRefreshResults) {
|
||||
makeWebCellRow(resultsInfo, row, dataFormat);
|
||||
continue;
|
||||
}
|
||||
List<DBDAttributeConstraint> constraints = new ArrayList<>();
|
||||
boolean hasKey = true;
|
||||
for (DBDAttributeBinding attr : resultsInfo.getAttributes()) {
|
||||
// get attributes only from row identifiers
|
||||
Set<DBDAttributeBinding> idAttributes = resultsInfo.getRowIdentifiers().stream()
|
||||
.flatMap(r -> r.getAttributes().stream())
|
||||
.collect(Collectors.toSet());
|
||||
for (DBDAttributeBinding attr : idAttributes) {
|
||||
if (attr.getRowIdentifier() == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -439,6 +449,7 @@ public class WebSQLProcessor implements WebSessionProvider {
|
||||
}
|
||||
if (!hasKey) {
|
||||
// No key value for this row
|
||||
makeWebCellRow(resultsInfo, row, dataFormat);
|
||||
continue;
|
||||
}
|
||||
DBDDataFilter filter = new DBDDataFilter(constraints);
|
||||
@@ -457,6 +468,20 @@ public class WebSQLProcessor implements WebSessionProvider {
|
||||
}
|
||||
}
|
||||
|
||||
private void makeWebCellRow(
|
||||
@NotNull WebSQLResultsInfo resultsInfo,
|
||||
@NotNull Object[] row,
|
||||
@Nullable WebDataFormat dataFormat
|
||||
) throws DBCException {
|
||||
for (int i = 0; i < row.length; i++) {
|
||||
row[i] = WebSQLUtils.makeWebCellValue(
|
||||
webSession,
|
||||
resultsInfo.getAttributeByPosition(i),
|
||||
row[i],
|
||||
dataFormat);
|
||||
}
|
||||
}
|
||||
|
||||
public String generateResultsDataUpdateScript(
|
||||
@NotNull DBRProgressMonitor monitor,
|
||||
@NotNull WebSQLContextInfo contextInfo,
|
||||
|
||||
+7
-2
@@ -57,6 +57,7 @@ import org.jkiss.utils.SecurityUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
@@ -458,8 +459,12 @@ public class CBDatabase {
|
||||
}
|
||||
|
||||
private void checkInstanceRecord(Connection connection) throws SQLException, IOException {
|
||||
InetAddress localHost = InetAddress.getLocalHost();
|
||||
String hostName = localHost.getHostName();
|
||||
String hostName;
|
||||
try {
|
||||
hostName = InetAddress.getLocalHost().getHostName();
|
||||
} catch (UnknownHostException e) {
|
||||
hostName = "localhost";
|
||||
}
|
||||
byte[] hardwareAddress = RuntimeUtils.getLocalMacAddress();
|
||||
String macAddress = CommonUtils.toHexString(hardwareAddress);
|
||||
|
||||
|
||||
@@ -107,6 +107,7 @@ export default [
|
||||
['ui_upload_file_fail', 'Failed to upload file'],
|
||||
['ui_filter', 'Filter'],
|
||||
['ui_disable', 'Disable'],
|
||||
['ui_test', 'Test'],
|
||||
|
||||
['root_permission_denied', "You don't have permissions"],
|
||||
['root_permission_no_permission', "You don't have permission for this action"],
|
||||
|
||||
@@ -91,6 +91,7 @@ export default [
|
||||
['ui_upload_file_fail', 'Failed to upload file'],
|
||||
['ui_filter', 'Filter'],
|
||||
['ui_disable', 'Disable'],
|
||||
['ui_test', 'Test'],
|
||||
|
||||
['root_permission_denied', 'Non hai i permessi'],
|
||||
['app_root_session_expire_warning_title', 'La sessione sta per scadere'],
|
||||
|
||||
@@ -103,6 +103,7 @@ export default [
|
||||
['ui_upload_file_fail', 'Не удалось загрузить файл'],
|
||||
['ui_filter', 'Фильтр'],
|
||||
['ui_disable', 'Отключить'],
|
||||
['ui_test', 'Проверить'],
|
||||
|
||||
['root_permission_denied', 'Отказано в доступе'],
|
||||
['root_permission_no_permission', 'У вас нет разрешения на это действие'],
|
||||
|
||||
@@ -104,6 +104,7 @@ export default [
|
||||
['ui_upload_file_fail', 'Failed to upload file'],
|
||||
['ui_filter', 'Filter'],
|
||||
['ui_disable', 'Disable'],
|
||||
['ui_test', 'Test'],
|
||||
|
||||
['root_permission_denied', '您没有权限'],
|
||||
['root_permission_no_permission', '您没有权限执行此操作'],
|
||||
|
||||
@@ -6,19 +6,11 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { Button, Container, GroupItem, useStyles, useTranslate } from '@cloudbeaver/core-blocks';
|
||||
import { Button, Container, useTranslate } from '@cloudbeaver/core-blocks';
|
||||
|
||||
import { useAuthenticationAction } from './useAuthenticationAction';
|
||||
|
||||
const styles = css`
|
||||
Container {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
`;
|
||||
|
||||
export type Props = {
|
||||
providerId: string;
|
||||
className?: string;
|
||||
@@ -29,21 +21,22 @@ export type Props = {
|
||||
|
||||
export const AuthenticationProvider = observer<Props>(function AuthenticationProvider(props) {
|
||||
const translate = useTranslate();
|
||||
const style = useStyles(styles);
|
||||
const action = useAuthenticationAction(props);
|
||||
|
||||
if (action.authorized) {
|
||||
return (props.children?.() as null) || null;
|
||||
}
|
||||
|
||||
return styled(style)(
|
||||
<Container className={props.className} gap vertical>
|
||||
<GroupItem keepSize>{translate('authentication_request_token')}</GroupItem>
|
||||
<GroupItem keepSize>
|
||||
<Button type="button" mod={['unelevated']} loading={action.authenticating} onClick={action.auth}>
|
||||
{translate('authentication_authenticate')}
|
||||
</Button>
|
||||
</GroupItem>
|
||||
</Container>,
|
||||
return (
|
||||
<Container className={props.className} gap vertical center>
|
||||
<Container keepSize center vertical gap dense>
|
||||
<Container keepSize>{translate('authentication_request_token')}</Container>
|
||||
<Container keepSize>
|
||||
<Button type="button" mod={['unelevated']} loading={action.authenticating} onClick={action.auth}>
|
||||
{translate('authentication_authenticate')}
|
||||
</Button>
|
||||
</Container>
|
||||
</Container>
|
||||
</Container>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -9,6 +9,7 @@ import { runInAction } from 'mobx';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { AUTH_PROVIDER_LOCAL_ID, AuthProvidersResource, UserInfoResource } from '@cloudbeaver/core-authentication';
|
||||
import {
|
||||
ColoredContainer,
|
||||
ExceptionMessage,
|
||||
@@ -20,7 +21,7 @@ import {
|
||||
useStyles,
|
||||
useTranslate,
|
||||
} from '@cloudbeaver/core-blocks';
|
||||
import { createConnectionParam } from '@cloudbeaver/core-connections';
|
||||
import { createConnectionParam, DatabaseAuthModelsResource, DBDriverResource } from '@cloudbeaver/core-connections';
|
||||
import { TabContainerPanelComponent, useTab, useTabState } from '@cloudbeaver/core-ui';
|
||||
|
||||
import type { IConnectionFormProps } from '../IConnectionFormProps';
|
||||
@@ -38,12 +39,25 @@ const style = css`
|
||||
}
|
||||
`;
|
||||
|
||||
export const OriginInfo: TabContainerPanelComponent<IConnectionFormProps> = observer(function OriginInfo({ tabId, state: { info, resource } }) {
|
||||
export const OriginInfo: TabContainerPanelComponent<IConnectionFormProps> = observer(function OriginInfo({
|
||||
tabId,
|
||||
state: { info, resource, config },
|
||||
}) {
|
||||
const tab = useTab(tabId);
|
||||
const translate = useTranslate();
|
||||
// const userInfoService = useService(UserInfoResource);
|
||||
const userInfoLoader = useResource(OriginInfo, UserInfoResource, undefined);
|
||||
const state = useTabState<Record<string, any>>();
|
||||
const styles = useStyles(style);
|
||||
const driverLoader = useResource(OriginInfo, DBDriverResource, config.driverId ?? null);
|
||||
const authModeLoader = useResource(
|
||||
OriginInfo,
|
||||
DatabaseAuthModelsResource,
|
||||
config.authModelId ?? info?.authModel ?? driverLoader.data?.defaultAuthModel ?? null,
|
||||
);
|
||||
|
||||
const providerId = authModeLoader.data?.requiredAuth ?? info?.requiredAuth ?? AUTH_PROVIDER_LOCAL_ID;
|
||||
const isAuthenticated = userInfoLoader.resource.hasToken(providerId);
|
||||
const providerLoader = useResource(OriginInfo, AuthProvidersResource, providerId);
|
||||
|
||||
const connection = useResource(
|
||||
OriginInfo,
|
||||
@@ -53,7 +67,7 @@ export const OriginInfo: TabContainerPanelComponent<IConnectionFormProps> = obse
|
||||
includes: ['includeOrigin', 'customIncludeOriginDetails'] as const,
|
||||
},
|
||||
{
|
||||
// isActive: () => !info?.origin || userInfoService.hasOrigin(info.origin),
|
||||
active: isAuthenticated,
|
||||
onData: connection => {
|
||||
runInAction(() => {
|
||||
if (!connection.origin.details) {
|
||||
@@ -89,15 +103,17 @@ export const OriginInfo: TabContainerPanelComponent<IConnectionFormProps> = obse
|
||||
);
|
||||
}
|
||||
|
||||
// const authorized = !info?.origin || userInfoService.hasOrigin(info.origin);
|
||||
|
||||
// if (!authorized && info?.origin) {
|
||||
// return styled(styles)(
|
||||
// <ColoredContainer parent vertical>
|
||||
// <AuthenticationProvider origin={info.origin} onAuthenticate={connection.reload} />
|
||||
// </ColoredContainer>
|
||||
// );
|
||||
// }
|
||||
if (!isAuthenticated) {
|
||||
return styled(styles)(
|
||||
<ColoredContainer parent>
|
||||
<TextPlaceholder>
|
||||
{translate('connections_public_connection_cloud_auth_required', undefined, {
|
||||
providerLabel: providerLoader.data?.label,
|
||||
})}
|
||||
</TextPlaceholder>
|
||||
</ColoredContainer>,
|
||||
);
|
||||
}
|
||||
|
||||
if (!connection.data?.origin.details || connection.data.origin.details.length === 0) {
|
||||
return styled(styles)(
|
||||
|
||||
Reference in New Issue
Block a user