ФУНКЦИИ - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: Plane live access и logout handoff
This commit is contained in:
@@ -7,8 +7,10 @@
|
||||
import React from "react";
|
||||
// components
|
||||
import { AuthBase } from "@/components/auth-screens/auth-base";
|
||||
import { NodeDCAuthRedirect } from "@/components/auth-screens/nodedc-auth-redirect";
|
||||
// helpers
|
||||
import { EAuthModes, EPageTypes } from "@/helpers/authentication.helper";
|
||||
import { shouldUseNodeDCOIDC } from "@/helpers/nodedc-auth";
|
||||
// layouts
|
||||
import DefaultLayout from "@/layouts/default-layout";
|
||||
// wrappers
|
||||
@@ -18,7 +20,7 @@ function HomePage() {
|
||||
return (
|
||||
<DefaultLayout>
|
||||
<AuthenticationWrapper pageType={EPageTypes.NON_AUTHENTICATED}>
|
||||
<AuthBase authType={EAuthModes.SIGN_IN} />
|
||||
{shouldUseNodeDCOIDC() ? <NodeDCAuthRedirect /> : <AuthBase authType={EAuthModes.SIGN_IN} />}
|
||||
</AuthenticationWrapper>
|
||||
</DefaultLayout>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { useEffect } from "react";
|
||||
|
||||
import { buildNodeDCOIDCLoginUrl, buildNodeDCLauncherUrl, sanitizeNextPath } from "@/helpers/nodedc-auth";
|
||||
|
||||
export function NodeDCAuthRedirect() {
|
||||
useEffect(() => {
|
||||
const currentUrl = new URL(window.location.href);
|
||||
const oidcError = currentUrl.searchParams.get("error");
|
||||
const nextPath = sanitizeNextPath(currentUrl.searchParams.get("next_path") || window.location.pathname);
|
||||
|
||||
if (oidcError === "oidc_access_denied" || oidcError === "nodedc_access_revoked") {
|
||||
window.location.replace(buildNodeDCLauncherUrl());
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.replace(buildNodeDCOIDCLoginUrl(nextPath));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="relative z-10 flex h-screen w-screen flex-col items-center justify-center overflow-hidden bg-canvas px-8 py-12">
|
||||
<div className="nodedc-auth-shell flex w-full max-w-[28rem] flex-col gap-4 text-center">
|
||||
<div className="text-2xl font-semibold text-custom-text-100">Переходим в NODE.DC</div>
|
||||
<div className="text-sm text-custom-text-300">Проверяем платформенную сессию и доступ к рабочему пространству.</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import useSWR from "swr";
|
||||
import { LogoSpinner } from "@/components/common/logo-spinner";
|
||||
// helpers
|
||||
import { EPageTypes } from "@/helpers/authentication.helper";
|
||||
import { buildNodeDCOIDCLoginUrl, getCurrentRelativePath, shouldUseNodeDCOIDC } from "@/helpers/nodedc-auth";
|
||||
// hooks
|
||||
import { useWorkspace } from "@/hooks/store/use-workspace";
|
||||
import { useUser, useUserProfile, useUserSettings } from "@/hooks/store/user";
|
||||
@@ -82,6 +83,15 @@ export const AuthenticationWrapper = observer(function AuthenticationWrapper(pro
|
||||
return redirectionRoute;
|
||||
};
|
||||
|
||||
const redirectToPlatformLogin = () => {
|
||||
if (shouldUseNodeDCOIDC()) {
|
||||
window.location.replace(buildNodeDCOIDCLoginUrl(getCurrentRelativePath()));
|
||||
return;
|
||||
}
|
||||
|
||||
router.push(`/${pathname ? `?next_path=${pathname}` : ``}`);
|
||||
};
|
||||
|
||||
if ((isUserSWRLoading || isUserLoading || workspacesLoader) && !currentUser?.id)
|
||||
return (
|
||||
<div className="relative flex h-screen w-full items-center justify-center">
|
||||
@@ -107,7 +117,7 @@ export const AuthenticationWrapper = observer(function AuthenticationWrapper(pro
|
||||
|
||||
if (pageType === EPageTypes.ONBOARDING) {
|
||||
if (!currentUser?.id) {
|
||||
router.push(`/${pathname ? `?next_path=${pathname}` : ``}`);
|
||||
redirectToPlatformLogin();
|
||||
return <></>;
|
||||
} else {
|
||||
if (currentUser && currentUserProfile?.id && isUserOnboard) {
|
||||
@@ -120,7 +130,7 @@ export const AuthenticationWrapper = observer(function AuthenticationWrapper(pro
|
||||
|
||||
if (pageType === EPageTypes.SET_PASSWORD) {
|
||||
if (!currentUser?.id) {
|
||||
router.push(`/${pathname ? `?next_path=${pathname}` : ``}`);
|
||||
redirectToPlatformLogin();
|
||||
return <></>;
|
||||
} else {
|
||||
if (currentUser && !currentUser?.is_password_autoset && currentUserProfile?.id && isUserOnboard) {
|
||||
@@ -139,7 +149,7 @@ export const AuthenticationWrapper = observer(function AuthenticationWrapper(pro
|
||||
return <></>;
|
||||
}
|
||||
} else {
|
||||
router.push(`/${pathname ? `?next_path=${pathname}` : ``}`);
|
||||
redirectToPlatformLogin();
|
||||
return <></>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
import type { AxiosInstance, AxiosRequestConfig } from "axios";
|
||||
import axios from "axios";
|
||||
|
||||
import { buildNodeDCOIDCLoginUrl, getCurrentRelativePath, shouldUseNodeDCOIDC } from "@/helpers/nodedc-auth";
|
||||
|
||||
export abstract class APIService {
|
||||
protected baseURL: string;
|
||||
private axiosInstance: AxiosInstance;
|
||||
@@ -26,9 +28,17 @@ export abstract class APIService {
|
||||
this.axiosInstance.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error) => {
|
||||
if (error.response && error.response.status === 401) {
|
||||
const status = error.response?.status;
|
||||
const responseError = error.response?.data?.error;
|
||||
|
||||
if (status === 401 || (status === 403 && responseError === "nodedc_access_revoked")) {
|
||||
const currentPath = window.location.pathname;
|
||||
window.location.replace(`/${currentPath ? `?next_path=${currentPath}` : ``}`);
|
||||
|
||||
if (shouldUseNodeDCOIDC()) {
|
||||
window.location.replace(buildNodeDCOIDCLoginUrl(getCurrentRelativePath()));
|
||||
} else {
|
||||
window.location.replace(`/${currentPath ? `?next_path=${currentPath}` : ``}`);
|
||||
}
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
export function shouldUseNodeDCOIDC(): boolean {
|
||||
const flag = process.env.VITE_NODEDC_OIDC_LOGIN_ENABLED;
|
||||
|
||||
if (flag === "1" || flag === "true") {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (flag === "0" || flag === "false") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof window === "undefined") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const hostname = window.location.hostname.toLowerCase();
|
||||
return hostname.endsWith(".local.nodedc") || hostname.endsWith(".notdc.ru") || hostname.endsWith(".nodedc.ru");
|
||||
}
|
||||
|
||||
export function buildNodeDCOIDCLoginUrl(nextPath?: string | null): string {
|
||||
const configuredUrl = process.env.VITE_NODEDC_OIDC_LOGIN_URL || "/auth/oidc/login/";
|
||||
const url = new URL(configuredUrl, window.location.origin);
|
||||
const safeNextPath = sanitizeNextPath(nextPath || getCurrentRelativePath());
|
||||
|
||||
if (safeNextPath) {
|
||||
url.searchParams.set("next_path", safeNextPath);
|
||||
}
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
export function buildNodeDCLauncherUrl(): string {
|
||||
return process.env.VITE_NODEDC_LAUNCHER_URL || "http://launcher.local.nodedc/";
|
||||
}
|
||||
|
||||
export function getCurrentRelativePath(): string {
|
||||
if (typeof window === "undefined") {
|
||||
return "/";
|
||||
}
|
||||
|
||||
return `${window.location.pathname}${window.location.search}`;
|
||||
}
|
||||
|
||||
export function sanitizeNextPath(value?: string | null): string {
|
||||
if (!value || !value.startsWith("/") || value.startsWith("//")) {
|
||||
return "/";
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
Reference in New Issue
Block a user