Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX-1893 Case insensitive comparison on server urls #1977

Merged
merged 10 commits into from
Aug 1, 2023
1 change: 1 addition & 0 deletions Src/Witsml/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Globalization;

namespace Witsml.Extensions
Expand Down
17 changes: 17 additions & 0 deletions Src/Witsml/Extensions/UriExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;

namespace Witsml.Extensions;

public static class UriExtensions
{
/// <summary>
/// Determines whether two specified Uri objects have the same value ignore case.
/// </summary>
/// The first Uri to compare.
/// The second Uri to compare.
/// <returns>True if the value of the <paramref name="firstUri" /> parameter is equal to the value of the <paramref name="secondUri" />, otherwise return false.</returns>
public static bool EqualsIgnoreCase(this Uri firstUri, Uri secondUri)
{
return string.Equals(firstUri?.AbsoluteUri, secondUri?.AbsoluteUri, StringComparison.OrdinalIgnoreCase);
}
}
9 changes: 6 additions & 3 deletions Src/WitsmlExplorer.Api/Configuration/ServerCredentials.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System;

using Witsml.Extensions;

namespace WitsmlExplorer.Api.Configuration
{
public class ServerCredentials : ICredentials, IEquatable<ServerCredentials>
Expand Down Expand Up @@ -26,9 +29,9 @@ public bool IsCredsNullOrEmpty()
}
public bool Equals(ServerCredentials other)
{
return (Host.ToString() == other.Host.ToString()) &&
(UserId == other.UserId) &&
(Password == other.Password);
return (Host.EqualsIgnoreCase(other.Host)) &&
(UserId == other.UserId) &&
(Password == other.Password);
}

public override bool Equals(object obj)
Expand Down
7 changes: 4 additions & 3 deletions Src/WitsmlExplorer.Api/Services/CredentialsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

using Witsml;
using Witsml.Data;
using Witsml.Extensions;

using WitsmlExplorer.Api.Configuration;
using WitsmlExplorer.Api.Extensions;
Expand Down Expand Up @@ -87,8 +88,8 @@ private async Task<bool> UserHasRoleForHost(string[] roles, Uri host)
bool result = true;
IEnumerable<Server> allServers = await _allServers;

bool systemCredsExists = _witsmlServerCredentials.WitsmlCreds.Any(n => n.Host == host);
IEnumerable<Server> hostServer = allServers.Where(n => n.Url.ToString() == host.ToString());
bool systemCredsExists = _witsmlServerCredentials.WitsmlCreds.Any(n => n.Host.EqualsIgnoreCase(host));
IEnumerable<Server> hostServer = allServers.Where(n => n.Url.EqualsIgnoreCase(host));
bool validRole = hostServer.Any(n =>
n.Roles != null && n.Roles.Intersect(roles).Any()
);
Expand Down Expand Up @@ -139,7 +140,7 @@ private async Task<ServerCredentials> GetSystemCredentialsByToken(string token,
_logger.LogDebug("User roles in JWT: {roles}", string.Join(",", userRoles));
if (await UserHasRoleForHost(userRoles, server))
{
result = _witsmlServerCredentials.WitsmlCreds.Single(n => n.Host == server);
result = _witsmlServerCredentials.WitsmlCreds.Single(n => n.Host.EqualsIgnoreCase(server));
if (!result.IsCredsNullOrEmpty())
{
CacheCredentials(GetClaimFromToken(token, SUBJECT), result, 1.0);
Expand Down
4 changes: 2 additions & 2 deletions Src/WitsmlExplorer.Api/Workers/Copy/CopyLogDataWorker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ public CopyLogDataWorker(IWitsmlClientProvider witsmlClientProvider, ILogger<Cop
Uri targetHostname = GetTargetWitsmlClientOrThrow().GetServerHostname();
Uri sourceHostname = GetSourceWitsmlClientOrThrow().GetServerHostname();
IEnumerable<Server> servers = _witsmlServerRepository == null ? new List<Server>() : await _witsmlServerRepository.GetDocumentsAsync();
int targetDepthLogDecimals = servers.FirstOrDefault((server) => server.Url == targetHostname)?.DepthLogDecimals ?? 0;
int sourceDepthLogDecimals = servers.FirstOrDefault((server) => server.Url == sourceHostname)?.DepthLogDecimals ?? 0;
int targetDepthLogDecimals = servers.FirstOrDefault((server) => server.Url.EqualsIgnoreCase(targetHostname))?.DepthLogDecimals ?? 0;
int sourceDepthLogDecimals = servers.FirstOrDefault((server) => server.Url.EqualsIgnoreCase(sourceHostname))?.DepthLogDecimals ?? 0;

(WitsmlLog sourceLog, WitsmlLog targetLog) = await GetLogs(job);
List<string> mnemonicsToCopy = job.Source.ComponentUids.Any()
Expand Down
2 changes: 1 addition & 1 deletion Src/WitsmlExplorer.Frontend/components/Alerts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const Alerts = (): React.ReactElement => {
}
});
const unsubscribeOnJobFinished = NotificationService.Instance.alertDispatcherAsEvent.subscribe((notification) => {
const shouldNotify = notification.serverUrl == null || notification.serverUrl.toString() === navigationState.selectedServer?.url;
const shouldNotify = notification.serverUrl == null || notification.serverUrl.toString().toLowerCase() === navigationState.selectedServer?.url?.toLowerCase();
if (!shouldNotify) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const JobsView = (): React.ReactElement => {

useEffect(() => {
const eventHandler = (notification: Notification) => {
const shouldFetch = notification.serverUrl.toString() === navigationState.selectedServer?.url;
const shouldFetch = notification.serverUrl.toString().toLowerCase() === navigationState.selectedServer?.url?.toLowerCase();
if (shouldFetch) {
setShouldRefresh(true);
}
Expand Down Expand Up @@ -152,7 +152,7 @@ const serverUrlToName = (servers: Server[], url: string): string => {
if (!url) {
return "-";
}
const server = servers.find((server) => server.url == url);
const server = servers.find((server) => server.url.toLowerCase() == url.toLowerCase());
return server ? server.name : url;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export const useColumnDef = (viewId: string, columns: ContentTableColumn[], inse
header: column.label,
size: savedWidths ? savedWidths[column.label] : calculateColumnWidth(column.label, isCompactMode, column.type),
meta: { type: column.type },
...addActiveCurveFiltering(column.label),
...addMeasureSorting(column.type)
sortingFn: column.type == ContentType.Measure ? measureSortingFn : "text",
...addActiveCurveFiltering(column.label)
};
});

Expand Down Expand Up @@ -57,14 +57,6 @@ const addActiveCurveFiltering = (columnLabel: string): Partial<ColumnDef<any, an
: {};
};

const addMeasureSorting = (contentType: ContentType): Partial<ColumnDef<any, any>> => {
return contentType == ContentType.Measure
? {
sortingFn: measureSortingFn
}
: {};
};

const getExpanderColumnDef = (isCompactMode: boolean): ColumnDef<any, any> => {
return {
id: expanderId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import AuthorizationService from "../../services/authorizationService";
import JobService, { JobType } from "../../services/jobService";

export const onClickPaste = (servers: Server[], sourceServerUrl: string, orderCopyJob: () => void) => {
const sourceServer = servers.find((server) => server.url === sourceServerUrl);
const sourceServer = servers.find((server) => server.url.toLowerCase() === sourceServerUrl.toLowerCase());
if (sourceServer !== null) {
AuthorizationService.setSourceServer(sourceServer);
orderCopyJob();
Expand Down
21 changes: 20 additions & 1 deletion Src/WitsmlExplorer.Frontend/components/Modals/SettingsModal.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { NativeSelect } from "@equinor/eds-core-react";
import { Button, NativeSelect } from "@equinor/eds-core-react";
import { Typography } from "@material-ui/core";
import React, { useContext } from "react";
import styled from "styled-components";
import OperationContext from "../../contexts/operationContext";
import { TimeZone, UserTheme } from "../../contexts/operationStateReducer";
import OperationType from "../../contexts/operationType";
import { getAccountInfo, msalEnabled, signOut } from "../../msal/MsalAuthProvider";
import AuthorizationService from "../../services/authorizationService";
import { Colors, dark, light } from "../../styles/Colors";
import Icon from "../../styles/Icons";
import { STORAGE_MODE_KEY, STORAGE_THEME_KEY, STORAGE_TIMEZONE_KEY } from "../Constants";
Expand Down Expand Up @@ -77,6 +80,22 @@ const SettingsModal = (): React.ReactElement => {
))}
</StyledNativeSelect>
</HorizontalLayout>
{msalEnabled && (
<HorizontalLayout>
<Typography style={{ margin: "auto 1rem auto 0" }}>Logged in to Azure AD as {getAccountInfo()?.name}</Typography>
<Button
onClick={() => {
const logout = async () => {
await AuthorizationService.deauthorize();
signOut();
};
logout();
}}
>
<Typography>Logout</Typography>
</Button>
</HorizontalLayout>
)}
</div>
}
onSubmit={() => dispatchOperation({ type: OperationType.HideModal })}
Expand Down
2 changes: 1 addition & 1 deletion Src/WitsmlExplorer.Frontend/components/RefreshHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const RefreshHandler = (): React.ReactElement => {

useEffect(() => {
const unsubscribe = NotificationService.Instance.refreshDispatcher.subscribe(async (refreshAction: RefreshAction) => {
const shouldTryRefresh = refreshAction?.serverUrl.toString() === selectedServer?.url;
const shouldTryRefresh = refreshAction?.serverUrl.toString().toLowerCase() === selectedServer?.url?.toLowerCase();
if (!shouldTryRefresh) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion Src/WitsmlExplorer.Frontend/components/Snackbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const Snackbar = (): React.ReactElement => {

useEffect(() => {
const unsubscribe = NotificationService.Instance.snackbarDispatcherAsEvent.subscribe((notification) => {
const shouldNotify = notification.serverUrl.toString() === navigationState.selectedServer?.url;
const shouldNotify = notification.serverUrl.toString().toLowerCase() === navigationState.selectedServer?.url?.toLowerCase();
if (shouldNotify) {
enqueueSnackbar(notification.message, {
variant: notification.isSuccess ? "success" : "error"
Expand Down
53 changes: 2 additions & 51 deletions Src/WitsmlExplorer.Frontend/components/TopRightCornerMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import { Button, Typography } from "@equinor/eds-core-react";
import { MenuItem } from "@material-ui/core";
import React, { ReactElement, useContext } from "react";
import { Button } from "@equinor/eds-core-react";
import React, { useContext } from "react";
import styled from "styled-components";
import NavigationContext from "../contexts/navigationContext";
import OperationContext from "../contexts/operationContext";
import OperationType from "../contexts/operationType";
import useDocumentDimensions from "../hooks/useDocumentDimensions";
import { getAccountInfo, msalEnabled, signOut } from "../msal/MsalAuthProvider";
import AuthorizationService from "../services/authorizationService";
import { Colors } from "../styles/Colors";
import Icon from "../styles/Icons";
import ContextMenu from "./ContextMenus/ContextMenu";
import JobsButton from "./JobsButton";
import { SettingsModal } from "./Modals/SettingsModal";
import UserCredentialsModal, { UserCredentialsModalProps } from "./Modals/UserCredentialsModal";
Expand All @@ -28,34 +25,6 @@ const TopRightCornerMenu = (): React.ReactElement => {
const { width: documentWidth } = useDocumentDimensions();
const showLabels = documentWidth > 1180;

const accountMenu = (
<ContextMenu
menuItems={[
<StyledMenuItem key={"account"}>
<Typography style={{ overflow: "clip", textOverflow: "ellipsis" }}>{getAccountInfo()?.name}</Typography>
</StyledMenuItem>,
<StyledMenuItem
key={"signout"}
onClick={() => {
const logout = async () => {
await AuthorizationService.deauthorize();
signOut();
};
logout();
dispatchOperation({ type: OperationType.HideContextMenu });
}}
>
<Typography>Logout</Typography>
</StyledMenuItem>
]}
/>
);

const onOpenMenu = (event: React.MouseEvent<HTMLButtonElement>, menu: ReactElement) => {
const position = { mouseX: event.currentTarget.getBoundingClientRect().left, mouseY: event.currentTarget.getBoundingClientRect().bottom };
dispatchOperation({ type: OperationType.DisplayContextMenu, payload: { component: menu, position } });
};

const openSettingsMenu = () => {
dispatchOperation({ type: OperationType.DisplayModal, payload: <SettingsModal /> });
};
Expand Down Expand Up @@ -85,12 +54,6 @@ const TopRightCornerMenu = (): React.ReactElement => {
<Icon name="settings" />
{showLabels && "Settings"}
</StyledButton>
{msalEnabled && (
<StyledButton colors={colors} variant={showLabels ? "ghost" : "ghost_icon"} onClick={(event: React.MouseEvent<HTMLButtonElement>) => onOpenMenu(event, accountMenu)}>
<Icon name="accountCircle" />
{showLabels && "Account"}
</StyledButton>
)}
</Layout>
);
};
Expand All @@ -108,16 +71,4 @@ const StyledButton = styled(Button)<{ colors: Colors }>`
white-space: nowrap;
`;

const StyledMenuItem = styled(MenuItem)`
&& {
width: 13rem;
display: flex;
flex-direction: row;
justify-content: space-between;
&&:focus {
outline: 0;
}
}
`;

export default TopRightCornerMenu;